Python 字符串不是不可变的吗?那么为什么 + ” ” +工作?
我的理解是 Python 字符串是不可变的。
我尝试了以下代码:
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
# !!!
Python 不应该阻止分配吗?我可能错过了一些东西。
有什么想法吗?
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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(22)
首先
a
指向字符串“Dog”。然后,您将变量a
更改为指向新字符串“Dog eats treats”。您实际上并没有改变字符串“Dog”。字符串是不可变的,变量可以指向它们想要的任何内容。First
a
pointed to the string "Dog". Then you changed the variablea
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.字符串对象本身是不可变的。
指向字符串的变量
a
是可变的。考虑:
The string objects themselves are immutable.
The variable,
a
, which points to the string, is mutable.Consider:
变量 a 指向对象“Dog”。最好将 Python 中的变量视为标签。您可以将标签移动到不同的对象,这就是您将
a = "dog"
更改为a = "dog eats treats"
时所做的操作。然而,不变性是指对象,而不是标签。
如果您尝试
a[1] = 'z'
将"dog"
转换为"dzg"
,您会收到错误:因为字符串不支持项目分配,因此它们是不可变的。
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"
toa = "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:because strings don't support item assignment, thus they are immutable.
仅当我们能够更改内存位置中保存的值而不更改内存位置本身时,某些东西才是可变的。
诀窍是:如果发现改变前后的内存位置相同,则它是可变的。
例如,列表是可变的。如何?
字符串是不可变的。我们如何证明这一点?
我们得到
因此我们未能改变字符串。这意味着字符串是不可变的。
在重新分配时,您将变量更改为指向新位置本身。这里你没有改变字符串,而是改变变量本身。以下是您正在做的事情。
重新分配前后的
id
是不同的,所以这证明你实际上没有改变,而是将变量指向新的位置。这不是改变该字符串,而是改变该变量。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 string is immutable. How do we prove it?
we get
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.
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
只是指向该内存地址的标签。它可以改变为指向任何东西。Consider:
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.变量只是指向对象的标签。该对象是不可变的,但如果您愿意,您可以使标签指向完全不同的对象。
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.
语句
a = a + " " + b + " " + c
可以根据指针进行分解。a + " "
表示给我a
指向的内容,该内容无法更改,并将" "
添加到我当前的工作集。memory:
+ b 表示给我 b 指向的内容,该内容无法更改,并将其添加到当前工作集中。
memory:
+ " " + c
表示将" "
添加到当前集合。然后给我c
指向的内容,该内容无法更改,并将其添加到当前工作集中。内存:
最后,
a =
表示将我的指针设置为指向结果集。内存:
"Dog"
被回收,因为不再有指针连接到它的内存块。我们从未修改过“Dog”
所在的内存部分,这就是不可变的含义。但是,我们可以更改哪些标签(如果有)指向该内存部分。The statement
a = a + " " + b + " " + c
can be broken down based upon pointers.a + " "
says give me whata
points to, which can't be changed, and add" "
to my current working set.memory:
+ b
says give me whatb
points to, which can't be changed, and add it to current working set.memory:
+ " " + c
says add" "
to the current set. Then give me whatc
points to, which can't be changed, and add it to current working set.memory:
Finally,
a =
says set my pointer to point to the resulting set.memory:
"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.数据和与其关联的标签之间存在差异。例如,当您执行此操作时,
将创建数据
“dog”
并将其放置在标签a
下。标签可以改变,但内存中的内容不会改变。在您执行此操作后,数据“dog”
仍将存在于内存中(直到垃圾收集器将其删除)。在您的程序
a
中,现在^指向^“cat”
但字符串"dog"
没有改变。There is a difference between data and the label it is associated with. For example when you do
the data
"dog"
is created and put under the labela
. 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 doIn your programm
a
now ^points to^"cat"
but the string"dog"
hasn't changed.Python 字符串对象是不可变的。
示例:
在此示例中,我们可以看到,当我们在 a 中分配不同的值时,它不会修改。创建一个新对象。
并且无法修改。
示例:
发生错误。
Python string objects are immutable.
Example:
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 error occurs.
Python 字符串是不可变的。但是,
a
不是字符串:它是具有字符串值的变量。您无法更改字符串,但可以将变量的值更改为新字符串。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.变量可以指向任何他们想要的地方。
如果执行以下操作,将会引发错误:
Variables can point to anywhere they want..
An error will be thrown if you do the following:
'mutable' 意味着我们可以改变字符串的内容,
“不可变”意味着我们不能添加额外的字符串。
'mutable' means that we can change the content of the string,
'immutable' means that we can't add an extra string.
<代码>>> a = '狗'
>>>>> a.replace('狗', '狗吃零食')
'狗吃零食'
>>> print a
'dogs'
不可变的,不是吗?!
变量改变部分已经讨论过了。
>>> a = 'dogs'
>>> a.replace('dogs', 'dogs eat treats')
'dogs eat treats'
>>> print a
'dogs'
Immutable, isn't it?!
The variable change part has already been discussed.
考虑在您的示例中添加此内容
我在博客中找到的更准确的解释之一是:
博客链接: https://jeffknupp .com/blog/2012/11/13/is-python-callbyvalue-or-callbyreference-neither/
Consider this addition to your example
One of the more precise explanations I found in a blog is:
Link to blog: https://jeffknupp.com/blog/2012/11/13/is-python-callbyvalue-or-callbyreference-neither/
在上述答案的基础上再补充一点。
变量的
id
在重新分配时会发生变化。这意味着我们已经改变了变量
a
以指向一个新字符串。现在存在两个string
(str) 对象:'initial_string'
,id
= 139982120425648和
' new_string'
withid
= 139982120425776考虑下面的代码:
现在,
b
指向'initial_string'
与重新分配之前的a
具有相同的id
。因此,
'intial_string'
尚未发生突变。Adding a bit more to above-mentioned answers.
id
of a variable changes upon reassignment.Which means that we have mutated the variable
a
to point to a new string. Now there exist twostring
(str) objects:'initial_string'
withid
= 139982120425648and
'new_string'
withid
= 139982120425776Consider the below code:
Now,
b
points to the'initial_string'
and has the sameid
asa
had before reassignment.Thus, the
'intial_string'
has not been mutated.内置函数
id()
以整数形式返回对象的标识。该整数通常对应于对象在内存中的位置。最初,“a”存储在 139831803293008 内存位置,因为字符串对象在 python 中是不可变的,如果您尝试修改和重新分配,引用将被删除,并将成为指向新内存位置的指针(139831803293120)。
The built-in function
id()
returns the identity of an object as an integer. This integer usually corresponds to the object’s location in memory.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).
总结:
不是不可变的:
不可变的:
这是 Python 3 中的一个错误,因为它是不可变的。在 Python 2 中这不是一个错误,因为显然它不是不可变的。
Summarizing:
Not immutable:
Immutable:
This is an error in Python 3 because it is immutable. And not an error in Python 2 because clearly it is not immutable.
我们只是连接两个字符串值。我们永远不会改变 (a) 的值。刚才(a)代表另一个具有“dogdog”值的内存块。因为在后端,一个变量永远不会同时代表两个内存块。连接前(a)的值为“dog”。但之后 (a) 代表“dogdog”,因为现在 (a) 在后端代表中。具有“dogdog”值的块。而“狗”是代表。在 (b) 代表“dog”之前,(b) 和“dog”不会被算作垃圾值。
令人困惑的是我们在后端用相同的变量名表示内存块(包含数据或信息)。
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.
您可以使 numpy 数组不可变并使用第一个元素:
then:
或
You can make a numpy array immutable and use the first element:
then:
or
这张图给出了答案。请阅读它。
This image gives the answer. Please read it.