- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我是 Python 的新手,正在尝试了解可变对象和不可变对象(immutable对象)之间的区别。 Python 中的一种可变类型是列表。假设 L = [1,2,3],那么 L 有一个指向对象 [1,2,3] 的 id。如果修改了 [1,2,3] 的内容,那么 L 仍然保留相同的 id。换句话说,即使对象的大小和内容已更改,L 仍与同一对象相关联。
对于不可变对象(immutable对象),我的理解是不允许修改对象。因此,如果一个变量被重新分配了一个新值,那么该变量将绑定(bind)到一个具有不同 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
中。
这种优化大部分都很好,因为引用计数检查确保它的行为大部分就好像字符串真的是不可变的并且创建了一个新字符串一样。但是,在 x = x + stuff
中,旧字符串和新字符串应该有短暂的重叠生命周期,因为新字符串应该在旧字符串赋值结束之前就已经存在string 的生命周期,因此 ID 值应该不可能相等。
id
是优化与未发生字符串突变时明显不同的少数几种方式之一。语言开发人员似乎已经决定接受这一点。
关于python - Python 中的可变和不可变,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56052904/
COW 不是奶牛,是 Copy-On-Write 的缩写,这是一种是复制但也不完全是复制的技术。 一般来说复制就是创建出完全相同的两份,两份是独立的: 但是,有的时候复制这件事没多大必要
我是一名优秀的程序员,十分优秀!