似乎反直觉的是, mutability 和 type 这两个正交概念被纠缠在一起而不是某种方式的可变限定类型,比如其他语言。
如果字符串和数字可以通过选择变化并执行替换和算术/位操作而不是每次都为结果创建新对象,那么它不会对性能有益吗?
我想到可能是这种方式(不可变的字符串和数字)来促进函数式编程,但Python并不是一种函数式编程语言。
这个问题不是关于什么是可变性/不变性或它们的利弊。
答案 0 :(得分:4)
可变性/不变性不仅仅是一个性能问题。变异对象意味着对对象的所有引用都会看到变化。对于某些类型,这会导致非常奇怪的行为:
def function(number_of_items):
n = number_of_items
# do some stuff. . .
n -= 1
# now the variable number_of_items was changed in the enclosing scope!
当涉及列表等可变类型时,这种行为已经让一些人感到惊讶,但对于数字类型来说更令人惊讶,因为人们期望例如数字3不能改变它的价值。
此外,可持续性(或至少哈希相关数据的不变性)对于可持续性是必需的。能够改变字符串意味着你不能再将它们用作字典键。你可以说只有不可变的字符串可以用作字典键,但这实际上会创建一个类型拆分。
Python的鸭子式哲学意味着类型基本上由他们所做的定义。如果两个对象在可变性等基本内容上有所不同,那么您无法以相同的方式使用它们,因此将它们视为相同的类型是没有意义的,即使它们名义上也是如此。同样地,使一种类型具有可变和不可变变体之间几乎没有实际区别,而不是两种类型的可变性变化 - 例如,具有可变和不可变列表与将list
和tuple
分开类型。
答案 1 :(得分:2)
让类型产生可变或不可变的实例无意义。他们的行为会彻底改变;一半的方法将不再有效,这使得应用优化变得更加困难。
您可以自由创建自己的类型,在某些情况下允许变异,在其他情况下是不可变的,但内置类型使用特定的优化,核心Python功能依赖于真正不可变的对象,而不是基于程序员首选项
程序员可以在类型之间自由切换; bytes
与bytearray
,tuple
与list
,frozenset
与set
的对比,{{1}}。
Python FAQ解决了字符串不可变的原因:
为什么Python字符串是不可变的?
有几个优点。
一个是性能:知道字符串是不可变的意味着我们可以在创建时为它分配空间,并且存储要求是固定且不变的。这也是区分元组和列表的原因之一。
另一个优点是Python中的字符串被视为数字的“元素”。没有多少活动会将值8更改为其他任何内容,而在Python中,任何活动量都不会将字符串“8”更改为其他任何内容。
除此之外,词典和集合使用哈希表,这是一种需要的算法,键只是通过它们的值来定位键是不可变的。
再次来自same FAQ:
为什么字典键必须是不可变的?
字典的哈希表实现使用从键值计算的哈希值来查找键。如果密钥是可变对象,则其值可能会发生变化,因此其哈希值也会发生变化。但是,由于无论谁更改密钥对象都无法判断它是否被用作字典密钥,因此无法在字典中移动条目。然后,当您尝试在字典中查找相同的对象时,将无法找到它,因为其哈希值不同。如果您尝试查找旧值,也不会找到它,因为在该哈希箱中找到的对象的值会有所不同。