python - 为什么 python 字符串和元组是不可变的?

标签 python string immutability tuples

我不确定为什么字符串和元组是不可变的;使它们不可变的优点和缺点是什么?

最佳答案

想象一种名为 FakeMutablePython 的语言,您可以在其中使用列表赋值等方式更改字符串(例如 mystr[0] = 'a')

a = "abc"

这会在内存地址 0x1 中创建一个条目,其中包含“abc”,以及指向它的标识符 a

现在,说你愿意..

b = a

这将创建标识符 b 并将其指向相同的内存地址 0x1

现在,如果字符串是可变的,并且您更改 b:

b[0] = 'z'

这会将存储在 0x1 的字符串的第一个字节更改为 z.. 由于标识符 a 指向此处,因此该字符串也会更改,因此..

print a
print b

..都会输出 zbc

这可能会导致一些非常奇怪、意想不到的行为。字典键就是一个很好的例子:

mykey = 'abc'
mydict = {
    mykey: 123,
    'zbc': 321
}

anotherstring = mykey
anotherstring[0] = 'z'

现在在 FakeMutablePython 中,事情变得相当奇怪 - 你最初在字典中有两个键,“abc”和“zbc”。然后你改变“abc”字符串(通过标识符 anotherstring ) 到 "zbc",所以 dict 有两个键,"zbc"和 "zbc"...

解决这个问题的一个方法是,每当您将字符串分配给标识符(或将其用作 dict 键)时,它会将字符串从 0x1 复制到 0x2。

这可以防止上述情况,但是如果你有一个需要 200MB 内存的字符串呢?

a = "really, really long string [...]"
b = a

你的脚本突然占用了 400MB 内存?这不是很好。

如果我们将它指向相同的内存地址,直到我们修改它,那会怎样? Copy on write .问题是,这可能非常复杂......

这就是不变性的用武之地。而不是要求 .replace() 方法将字符串从内存复制到新地址,然后修改它并返回。我们只是制作所有字符串不可变,因此该函数必须创建一个新字符串才能返回。这解释了以下代码:

a = "abc"
b = a.replace("a", "z")

并被证明:

>>> a = 'abc'
>>> b = a
>>> id(a) == id(b)
True
>>> b = b.replace("a", "z")
>>> id(a) == id(b)
False

(id()函数返回对象的内存地址)

关于python - 为什么 python 字符串和元组是不可变的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1538663/

相关文章:

tree - 本地编辑纯功能树

python - 如何使用 python 比较机器人框架的数据输出

regex - D:用逗号分割字符串,但不带引号的字符串

c++ - 如何将字符串的第一个字符传递给char?

dictionary - 在 React 中迭代不可变映射的键

sql - 数据库对不可变字段的支持

python - 如何使用Plotly绘制多个饼图圆圈?

python - 你如何在 Python 中旋转一个字符串数组?

python - 在 Maya 2013 中使用 lxml?

java - .equals ("0") 和 .equals ('0' ) 之间的区别