其中哪些在Python中是不可变的?

其中哪些在Python中是不可变的?,python,immutability,Python,Immutability,我试图弄清楚以下内容在Sage中是否是不可变的(它是基于Python构建的,因此我相信如果它在Python中是不可变的,那么我相信在大多数情况下它在Sage中是不可变的) 下面是对象e、f、g、i class e: pass f = e() g = pi # (g's "type" in Sage is symbolic expression. It's supposed to be 3.1415....etc) i = lambda x: x*x 我推测e是一个类,这意味着它是可变的(不可变

我试图弄清楚以下内容在Sage中是否是不可变的(它是基于Python构建的,因此我相信如果它在Python中是不可变的,那么我相信在大多数情况下它在Sage中是不可变的)

下面是对象e、f、g、i

class e: pass
f = e()
g = pi # (g's "type" in Sage is symbolic expression. It's supposed to be 3.1415....etc)
i = lambda x: x*x
我推测e是一个类,这意味着它是可变的(不可变的类有意义吗?难道不能修改所有的类吗?)。因为f是一个类的实例,我猜它也是可变的,因为类是可变的

因为数字在Python中是不可变的,所以g也应该是不可变的,因为它是一个数字,尽管它是无理的

最后,我是一个函数,这意味着它应该是可变的


我不太确定我是否理解不变性的概念。函数不可变意味着什么?类是不可变的吗?

e
是可变的。例如,您可以在类上添加一个新方法:
e.foo=lambda self,x:x

f
是可变的。例如,您可以将一个新字段添加到此类实例:
f.x=99

g
是不可变的。你不能改变任何事情

i
不是不变的。你可以对它做各种各样的坏事:
i.func\u code=(lambda x:123)。func\u code
之后,
i(10)
将是123而不是100。(您还可以对其进行更合理的处理。在
i.\uu doc\uu=“此函数返回其参数的平方。”
您将从
help(i)
获得更有用的结果)


如果您可以对对象执行某些更改其未来可能行为的操作,那么对象是可变的。您无法更改
10
的行为;您可以更改函数对象、类、类实例或列表的行为。(但不是元组。一旦元组被创建,它就一直保持原样。)

正式吗?如果一个对象可以在不改变标识的情况下改变值,那么它是可变的

列表是可变的,因此特定实例的值可以随时间变化:

>>> x = orig_x = []
>>> x == []
True
>>> x += [1]
>>> x == []      # The value of x has changed
False
>>> x is orig_x  # But the identity remains the same
True
然而,数字是不可变的,所以它们的值不能改变。相反,必须更新变量以引用完全不同的对象:

>>> x = orig_x = 1
>>> x == 1
True
>>> x += 1
>>> x == 1        # Again, the value of x has changed
False
>>> x is orig_x   # But now the identity has changed as well
False
不变性是一个重要的概念,因为知道对象的值不能改变可以让你对它做出某些假设(例如,
dict
实际上需要不可变的键,
set
frozenset
需要不可变的成员,因为对象的值会影响它在数据结构中的存储方式。如果允许可变条目,则如果在存储后对其进行修改,它们可能最终会出现在错误的位置)

与流行的观点相反,不覆盖相等定义的用户定义类在技术上是不可变的。这是因为用户定义类的“值”的默认定义只是
id(self)
。当一个对象的值是它的标识时,它们显然没有办法随着时间的推移而有所不同,因此该对象的质量不是“可变的”


非正式地?大多数人使用一个直观的“我能改变它吗?”定义,与加雷思·麦考汉的答案大致相同。这与正式定义的基本思想相同,只是使用了“价值”一词的更广泛含义严格地说,
dict
/
set
/
frozenset
只强制要求对象是可散列的,而不是完全不可变的。但是,如果您的键/元素不是真正不可变的,您可能会出现严重的奇怪行为。另请参见:.正如该简介所指出的,可变和不可变之间的界限有时会变得模糊。只有当元组引用的所有内容都是不可变的时,关于元组的评论才是真的。嗯,有点。更改元组引用的其他内容并不是真的对元组做什么。但我接受你的观点。有趣的是文档中的定义与您的解释一致(即元组被正式认为是不可变的,即使它们的值会随着时间的推移而变化):如果我对它完全是计算机科学,我建议我们确实需要两个不可变的概念——称它们为“局部不可变”和“传递不可变”或者,第一个意思是“你对对象所做的任何事情都不会改变它的行为”,第二个意思相当于(1)“对象是局部不可变的,从它可以到达的所有东西也是如此”和(2)“你使用对象所做的任何事都不会改变它的行为”.是的,重读Python文档中的定义提醒了我,一旦你开始考虑“这取决于你所说的不可变”的情况,在它们之间划清界线是多么棘手。