简体   繁体   English

Python中的可变和不可变

[英]Mutable and Immutable in Python

I am new to Python and trying to understand the difference between mutable and immutable objects. 我是Python新手,试图理解可变对象和不可变对象之间的区别。 One of the mutable types in Python is list. Python中的一个可变类型是list。 Let's say L = [1,2,3], then L has a id that points the object [1,2,3]. 假设L = [1,2,3],则L有一个id指向对象[1,2,3]。 If the content of [1,2,3] is modified then L still retains the same id. 如果[1,2,3]的内容被修改,那么L仍然保留相同的id。 In other words L is still associated with the same object even though the size and content of the object has been altered. 换句话说,即使对象的大小和内容已被改变,L仍然与相同的对象相关联。

With immutable objects, my understanding is that modification of the object isn't allowed. 对于不可变对象,我的理解是不允许修改对象。 Therefore, if a variable is reassigned with a new value, then that variable is bind to a new object with a different id. 因此,如果使用新值重新分配变量,则该变量将绑定到具有不同id的新对象。 I expect string to behave in similar manner. 我希望字符串的行为方式类似。 Yet I tried to modified a string but the string id didn't change. 然而我试图修改一个字符串,但字符串id没有改变。

string = "blue"
for i in range(10):
    string = string + str(i)
    print("string id after {}th iteration: {}".format(i,id(string)))


string id after 0th iteration: 46958272
string id after 1th iteration: 46958272
string id after 2th iteration: 46958272
string id after 3th iteration: 47077400
string id after 4th iteration: 47077400
string id after 5th iteration: 47077400
string id after 6th iteration: 47077400
string id after 7th iteration: 47077400
string id after 8th iteration: 47077400
string id after 9th iteration: 47077400

You really shouldn't see the same ID twice in a row, but CPython has an optimization for string concatenation with + that doesn't quite obey all the rules it's supposed to. 你真的不应该连续两次看到相同的ID,但CPython有一个优化的字符串连接+ ,它不完全遵守它应该的所有规则。

When CPython sees an operation of the form x = x + something or x += something , if x refers to a string and x holds the only reference to that string, then CPython will grow the string with realloc instead of creating a new string object. 当CPython看到x = x + somethingx += something形式的操作时,如果x引用一个字符串并且x保存对该字符串的唯一引用,那么CPython将使用realloc增长该字符串而不是创建一个新的字符串对象。 Depending on details of available memory, realloc may resize the allocated memory in place, or it may allocate new memory. 根据可用内存的详细信息, realloc可以调整已分配的内存大小,也可以分配新内存。 If it resizes the allocation, the object's id remains the same. 如果它调整分配大小,则对象的id保持不变。 You can see the implementation in unicode_concatenate in Python/ceval.c . 您可以在Python/ceval.c中的unicode_concatenate中看到实现。

This optimization is mostly fine, because the refcount check ensures it behaves mostly as if strings were really immutable and a new string was created. 这种优化大多很好,因为refcount检查确保它的行为大部分就像字符串真的是不可变的并且创建了一个新的字符串。 However, in x = x + stuff , the old string and the new string should have briefly overlapping lifetimes, because the new string should come into existence before the assignment ends the old string's lifetime, so it should be impossible for the ID values to be equal. 然而,在x = x + stuff ,老的字符串和新字符串应该有短暂重叠的寿命,因为新的字符串应该进入存在分配结束旧字符串的生命周期之前,所以它应该是不可能的ID值是等于。

id is one of the few ways the optimization is observably different from if no string mutation occurred. 如果没有发生字符串突变,则id是优化与显着不同的几种方式之一。 The language developers seem to have decided they're okay with that. 语言开发人员似乎已经决定他们对此没问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM