我是Python的新手,试图了解可变和不可变对象之间的区别。Python中的可变类型之一是列表。假设L = [1,2,3],则L具有指向对象[1,2,3]的ID。如果[1,2,3]的内容被修改,则L仍保留相同的id。换句话说,即使对象的大小和内容已更改,L仍与同一对象关联。
对于不可变的对象,我的理解是不允许修改对象。因此,如果使用新值重新分配变量,则该变量将绑定到具有不同ID的新对象。我希望字符串的行为类似。但是我尝试修改一个字符串,但是字符串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
您确实不应该连续两次看到相同的ID,但是CPython对字符串连接进行了优化,但+
并没有完全遵守它应该遵循的所有规则。
当CPython看到形式为x = x + something
或的操作时x += something
,如果x
引用一个字符串并x
保存对该字符串的唯一引用,则CPython将使用realloc
来扩展该字符串,而不是创建新的字符串对象。根据可用内存的详细信息,realloc
可能会在适当位置调整已分配内存的大小,或者可能会分配新内存。如果它调整分配大小,则对象的id
保持不变。您可以在unicode_concatenate
中查看实现Python/ceval.c
。
这种优化在大多数情况下都很好,因为refcount检查可确保它的行为几乎就像字符串确实是不可变的,并且创建了新的字符串一样。但是,在中x = x + stuff
,旧字符串和新字符串的生存期应短暂重叠,因为新字符串应在赋值结束旧字符串的生存期之前就已存在,因此ID值应该不可能相等。
id
这是优化的显着不同于未发生字符串突变的几种方法之一。语言开发人员似乎已经决定可以接受。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句