为什么真正的不变性在Python中是不可能的?



我正在阅读attrs的文档。它说:

请注意,真正的不变性在Python中是不可能的

我想知道是什么原因。为什么有人不能在Python中拥有不可变列表,而在c++中是可能的?这里的主要区别是什么?

TLDR; 真正的不变性只有在不透水的石碑上才有可能,但它与关于可变性的讨论是相反的,为什么使用它/是很重要的。在技术上是正确的不值得以实际错误为代价。

这是一个错误的语义论证。Python允许在强类型语言中重新定义不同类型的变量名,这就是一些混淆的来源,但要清楚的是,变量名所引用的对象非常可能是正确不可变的。

以包含几个数字的元组为例:

>>> tup_A = (1,2,3)

不能改变元组中任何对象的值:

>>> tup_A[0] = 10
TypeError: 'tuple' object does not support item assignment

可以用其他值覆盖变量名称tup_A,但是即使它与原始对象相关,它也将是一个完全不同的对象。例如,元组的切片创建了一个全新的对象,而不是原始对象的视图:

>>> id(tup_A)
2887473131072
>>> tup_A = tup_A[:1]
>>> id(tup_A)
2887473037616

我相信这篇文章提到的也可能在某种程度上指的是创建自定义不可变类型(类)的可能性。这也是一个糟糕的论点,因为有很多机制可以强制执行不变性。特别是,用于自定义属性访问的工具和@property函数可以在这方面发挥很大的作用。一旦使用这些方法来实现不变性,就必须故意破坏类来改变不打算改变的数据。这当然是可能的,因为python主要是作为源代码分发的,但从理论上讲,python c api也是如此。如果你重写python,元组不一定是不可变的,但这远远超出了重点,可以说这是错误的。

不变性是一种具有特定目的的工具。尽可能使用它是一个好主意,这样意外的失误将产生一个错误消息,而不是一个无声的错误。如果你遇到这样的错误,你不应该问"我如何改变这个不可变的值",而应该问"为什么这个值不能被改变,我打算如何利用它?">

注:您甚至可以使用ctypes库通过获取包含在其中的对象的实际内存位置并覆盖指针来在不编辑cpython的情况下改变元组,但这会破坏很多东西(如垃圾收集引用计数)。不要这样做。这是另一个"离题太远了"的东西。

实际上,像c++这样的其他语言将变量视为存储容器。但是Python将它们视为对内存地址的引用。列表可以就地修改,即在相同的内存位置。但是我们有元组,其值不能就地更新。

我不知道为什么python这样对待变量,但我认为这是必要的动态类型。真正的不变性是不可能的,可能是指动态打字功能。你可以谷歌一下了解更多。

如果这是你想要的,请告诉我。

如果内存是可变的,那么真正的不可变性是不可能的。

把不可变性看作是检查,而不是硬保证一切都保持不变。

最新更新