use*_*477 49 python string tuples immutability
我不确定为什么字符串和元组是不可变的; 使它们不可变的优点和缺点是什么?
dbr*_*dbr 75
想象一下名为FakeMutablePython的语言,您可以使用列表赋值等方式更改字符串(例如mystr[0] = 'a')
a = "abc"
Run Code Online (Sandbox Code Playgroud)
这会在内存地址0x1中创建一个条目,其中包含"abc"和a指向它的标识符.
现在,说你做..
b = a
Run Code Online (Sandbox Code Playgroud)
这将创建标识符,b并将其指向相同的内存地址0x1
现在,如果字符串是可变的,那么你改变了b:
b[0] = 'z'
Run Code Online (Sandbox Code Playgroud)
这z会将存储在0x1的字符串的第一个字节更改为..由于标识符a指向此处,因此该字符串也会更改,因此..
print a
print b
Run Code Online (Sandbox Code Playgroud)
..两者都会输出 zbc
这可能会导致一些非常奇怪的,意外的行为.字典键就是一个很好的例子:
mykey = 'abc'
mydict = {
mykey: 123,
'zbc': 321
}
anotherstring = mykey
anotherstring[0] = 'z'
Run Code Online (Sandbox Code Playgroud)
现在在FakeMutablePython中,事情变得相当奇怪 - 你最初在字典中有两个键,"abc"和"zbc"..然后你将"abc"字符串(通过标识符anotherstring)改为"zbc",所以dict有两个键,"zbc"和"zbc"......
这种奇怪的一种解决方案是,无论何时将字符串分配给标识符(或将其用作dict键),它都会将字符串复制为0x1到0x2.
这可以防止上述情况,但是如果你有一个需要200MB内存的字符串呢?
a = "really, really long string [...]"
b = a
Run Code Online (Sandbox Code Playgroud)
突然你的脚本需要400MB的内存?这不是很好.
如果我们将它指向相同的内存地址,直到我们修改它呢?复制写.问题是,这可能很复杂.
这就是不变性的来源.而不是要求.replace()方法将字符串从内存复制到新地址,然后修改它并返回..我们只是使所有字符串不可变,因此该函数必须创建一个新的字符串返回.这解释了以下代码:
a = "abc"
b = a.replace("a", "z")
Run Code Online (Sandbox Code Playgroud)
并证明:
>>> a = 'abc'
>>> b = a
>>> id(a) == id(b)
True
>>> b = b.replace("a", "z")
>>> id(a) == id(b)
False
Run Code Online (Sandbox Code Playgroud)
(该id()函数返回对象的内存地址)
Nas*_*sir 33
一个是性能:知道字符串是不可变的,这使得在构建时很容易将其布局 - 固定且不变的存储要求.这也是区分元组和列表的原因之一.这也允许实现安全地重用字符串对象.例如,CPython实现使用预分配的对象用于单字符字符串,并且通常返回不更改内容的字符串操作的原始字符串.
另一个是Python中的字符串被视为数字的"元素".没有多少活动会将值8更改为其他任何内容,而在Python中,任何活动量都不会将字符串"8"更改为其他任何内容.
http://effbot.org/pyfaq/why-are-python-strings-immutable.htm
使它们不可变的一大优点是它们可以用作字典中的键.我确定如果允许更改密钥,字典使用的内部数据结构会变得非常混乱.