a ="Dog"
b ="eats"
c ="treats"print a, b, c
# Dog eats treatsprint a +" "+ b +" "+ c
# Dog eats treatsprint a
# Dog
a = a +" "+ b +" "+ c
print a
# Dog eats treats# !!!
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?
回答 0
首先a指向字符串“ Dog”。然后,您将变量更改a为指向新的字符串“ Dog eats对待”。您实际上并未更改字符串“ Dog”。字符串是不可变的,变量可以指向它们想要的任何东西。
First a pointed to the string “Dog”. Then you changed the variable a to point at a new string “Dog eats treats”. You didn’t actually mutate the string “Dog”. Strings are immutable, variables can point at whatever they want.
回答 1
字符串对象本身是不可变的。
a指向字符串的变量是可变的。
考虑:
a ="Foo"# a now points to "Foo"
b = a
# b points to the same "Foo" that a points to
a = a + a
# a points to the new string "FooFoo", but b still points to the old "Foo"print a
print b
# Outputs:# FooFoo# Foo# Observe that b hasn't changed, even though a has.
The variable, a, which points to the string, is mutable.
Consider:
a = "Foo"
# a now points to "Foo"
b = a
# b points to the same "Foo" that a points to
a = a + a
# a points to the new string "FooFoo", but b still points to the old "Foo"
print a
print b
# Outputs:
# FooFoo
# Foo
# Observe that b hasn't changed, even though a has.
The variable a is pointing at the object “Dog”. It’s best to think of the variable in Python as a tag. You can move the tag to different objects which is what you did when you changed a = "dog" to a = "dog eats treats".
However, immutability refers to the object, not the tag.
If you tried a[1] = 'z' to make "dog" into "dzg", you would get the error:
TypeError: 'str' object does not support item assignment"
because strings don’t support item assignment, thus they are immutable.
回答 3
只有当我们能够更改存储位置中保存的值而不更改存储位置本身时,某些事情才是可变的。
诀窍是:如果发现更改前后的内存位置相同,则它是可变的。
例如,列表是可变的。怎么样?
>> 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 ="hello"> a[0]'h'# Now let's modify it> a[0]='n'----------------------------------------------------------------------
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'
----------------------------------------------------------------------
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.
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.
回答 5
考虑:
>>> 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>
>>> 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
该语句a = a + " " + b + " " + c可以基于指针进行分解。
a + " "说给我a指向什么,不能更改,然后添加" "到我当前的工作集中。
记忆:
working_set ="Dog "
a ="Dog"
b ="eats"
c ="treats"
+ b告诉我要b指向的内容,不能更改的内容,然后将其添加到当前工作集中。
记忆:
working_set ="Dog eats"
a ="Dog"
b ="eats"
c ="treats"
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.
回答 7
l =[1,2,3]print id(l)
l.append(4)print id(l)#object l is the same
a ="dog"print id(a)
a ="cat"print id(a)#object a is a new object, previous one is deleted
l = [1,2,3]
print id(l)
l.append(4)
print id(l) #object l is the same
a = "dog"
print id(a)
a = "cat"
print id(a) #object a is a new object, previous one is deleted
There is a difference between data and the label it is associated with. For example when you do
a = "dog"
the data "dog" is created and put under the label a. The label can change but what is in the memory won’t. The data "dog" will still exist in memory (until the garbage collector deletes it) after you do
a = "cat"
In your programm a now ^points to^ "cat" but the string "dog" hasn’t changed.
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.
回答 10
变量可以指向它们想要的任何位置。如果执行以下操作,将引发错误:
a ="dog"print a #dog
a[1]="g"#ERROR!!!!!! STRINGS ARE IMMUTABLE
Variables can point to anywhere they want..
An error will be thrown if you do the following:
a = "dog"
print a #dog
a[1] = "g" #ERROR!!!!!! STRINGS ARE IMMUTABLE
回答 11
Python字符串对象是不可变的。例:
>>> a ='tanim'>>>'Address of a is:{}'.format(id(a))'Address of a is:64281536'>>> a ='ahmed'>>>'Address of a is:{}'.format(id(a))'Address of a is:64281600'
>>> a = 'tanim'
>>> 'Address of a is:{}'.format(id(a))
'Address of a is:64281536'
>>> a = 'ahmed'
>>> 'Address of a is:{}'.format(id(a))
'Address of a is:64281600'
In this example we can see that when we assign different value in a it doesn’t modify.A new object is created.
And it can’t be modified.
Example:
>>> a[0] = 'c'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
**TypeError**: 'str' object does not support item assignment
a = "Dog"
b = "eats"
c = "treats"
print (a,b,c)
#Dog eats treats
d = a + " " + b + " " + c
print (a)
#Dog
print (d)
#Dog eats treats
One of the more precise explanations I found in a blog is:
In Python, (almost) everything is an object. What we commonly refer to as “variables” in Python are more properly called names. Likewise, “assignment” is really the binding of a name to an object. Each binding has a scope that defines its visibility, usually the block in which the name originates.
Eg:
some_guy = 'Fred'
# ...
some_guy = 'George'
When we later say some_guy = ‘George’, the string object containing ‘Fred’ is unaffected. We’ve just changed the binding of the name some_guy. We haven’t, however, changed either the ‘Fred’ or ‘George’ string objects. As far as we’re concerned, they may live on indefinitely.
Initially, ‘a’ is stored in 139831803293008 memory location, as the string object is immutable in python if you try to modify and reassign the reference will be removed and will be a pointer to a new memory location(139831803293120).
回答 18
a ='dog'
address = id(a)print(id(a))
a = a +'cat'print(id(a))#Address changesimport ctypes
ctypes.cast(address, ctypes.py_object).value #value at old address is intact
a = 'dog'
address = id(a)
print(id(a))
a = a + 'cat'
print(id(a)) #Address changes
import ctypes
ctypes.cast(address, ctypes.py_object).value #value at old address is intact
We r just concatenate the two string values. We never change the value of (a). Just now (a) represent another memory block that has “dogdog” value. Because in the backend, one variable never represent two memory blocks at same time. The value of (a) before concatenation was “dog”. But after that (a) represent the “dogdog”, because now (a) in backend rep. the block that has “dogdog” value. And “dog” is rep. by (b) and “dog” isn’t counted as garbage value until (b) represent the “dog”.
The confusion is we represent the memory blocks(that contain data or info.) in backend with same variable name.