Python中的可变和不可变

时间:2019-05-09 05:44:25

标签: python immutability mutable

我是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

1 个答案:

答案 0 :(得分:2)

您实际上不应该连续两次看到相同的ID,但是CPython对+进行的字符串连接进行了优化,但并没有完全遵守应有的所有规则。

当CPython看到x = x + somethingx += something形式的操作时,如果x引用一个字符串,并且x保留 only 引用到该字符串,则CPython将使用realloc扩展字符串,而不是创建新的字符串对象。根据可用内存的详细信息,realloc可能会在适当位置调整已分配内存的大小,也可能会分配新内存。如果它调整分配大小,则对象的id保持不变。您可以在Python/ceval.c的{​​{3}}中看到实现。

此优化主要是,因为refcount检查可确保其表现为主要是,就好像字符串实际上是不可变的,并且创建了新的字符串一样。但是,在x = x + stuff中,旧字符串和新字符串具有短暂重叠的生存期,因为新字符串应在赋值结束旧字符串的生存期之前就已存在,因此 ID值相等应该是

id是优化的显着不同于未发生字符串突变的几种方法之一。语言开发人员似乎已经决定对此表示满意。