Aren't Python strings immutable? Then why does

2019-01-03 02:11发布

My understanding was that Python strings are immutable.

I tried the following code:

a = "Dog"
b = "eats"
c = "treats"

print a, b, c
# Dog eats treats

print a + " " + b + " " + c
# Dog eats treats

print a
# Dog

a = a + " " + b + " " + c
print a
# Dog eats treats
# !!!

Shouldn't Python have prevented the assignment? I am probably missing something.

Any idea?

18条回答
Viruses.
2楼-- · 2019-01-03 02:19

A variable is just a label pointing to an object. The object is immutable, but you can make the label point to a completely different object if you want to.

查看更多
仙女界的扛把子
3楼-- · 2019-01-03 02:21

Python strings are immutable. However, a is not a string: it is a variable with a string value. You can't mutate the string, but can change what value of the variable to a new string.

查看更多
ゆ 、 Hurt°
4楼-- · 2019-01-03 02:24

The statement a = a + " " + b + " " + c can be broken down based upon pointers.

a + " " says give me what a points to, which can't be changed, and add " " to my current working set.

memory:

working_set = "Dog "
a = "Dog" 
b = "eats"
c = "treats"

+ b says give me what b points to, which can't be changed, and add it to current working set.

memory:

working_set = "Dog eats"
a = "Dog" 
b = "eats"
c = "treats"

+ " " + c says add " " to the current set. Then give me what c points to, which can't be changed, and add it to current working set. memory:

working_set = "Dog eats treats"
a = "Dog" 
b = "eats"
c = "treats"

Finally, a = says set my pointer to point to the resulting set.

memory:

a = "Dog eats treats"
b = "eats"
c = "treats"

"Dog" is reclaimed, because no more pointers connect to it's chunk of memory. We never modified the memory section "Dog" resided in, which is what is meant by immutable. However, we can change which labels, if any, point to that section of memory.

查看更多
Summer. ? 凉城
5楼-- · 2019-01-03 02:24

Consider:

>>> a='asdf'
>>> a.__repr__
<method-wrapper '__repr__' of str object at 0x1091aab90>
>>> a='asdf'
>>> a.__repr__
<method-wrapper '__repr__' of str object at 0x1091aab90>
>>> a='qwer'
>>> a.__repr__
<method-wrapper '__repr__' of str object at 0x109198490>

Notice that the hex memory location did not change when I stored the same value in the variable twice. It did change when I stored a different value. The string is immutable. Not because of zealotry, but because you pay the performance penalty of creating a new object in memory. The variable a is just a label pointing to that memory address. It can be altered to point to anything.

查看更多
何必那么认真
6楼-- · 2019-01-03 02:26

You can make a numpy array immutable and use the first element:

numpyarrayname[0] = "write once"

then:

numpyarrayname.setflags(write=False)

or

numpyarrayname.flags.writeable = False
查看更多
一纸荒年 Trace。
7楼-- · 2019-01-03 02:27

Something is mutable only when we are able to change the values held in the memory location without changing the memory location itself.

The trick is: If you find that the memory location before and after the change are the same, it is mutable.

For example, list is mutable. How?

>> a = ['hello']
>> id(a)
139767295067632

# Now let's modify
#1
>> a[0] = "hello new"
>> a
['hello new']
Now that we have changed "a", let's see the location of a
>> id(a)
139767295067632
so it is the same as before. So we mutated a. So list is mutable.

A string is immutable. How do we prove it?

> a = "hello"
> a[0]
'h'
# Now let's modify it
> a[0] = 'n'
----------------------------------------------------------------------

we get

TypeError: 'str' object does not support item assignment

So we failed mutating the string. It means a string is immutable.

In you reassigning, you change the variable to point to a new location itself. Here you have not mutated the string, but mutating the variable itself. The following is what you are doing.

>> a = "hello"
>> id(a)
139767308749440
>> a ="world"
>> id(a)
139767293625808

id before and after reassignment is different, so it this proves that you are actually not mutating, but pointing the variable to new location. Which is not mutating that string, but mutating that variable.

查看更多
登录 后发表回答