为什么Python中的"&="集合操作符和"&="整数操作表现不同?

5
为什么这个集合操作会改变集合s?对于整数(按位)版本的同一运算符,它的工作方式不同......
集合操作&=(会改变s):
s = set('abc')
t = set('bcd')
u=s
print u, s, t
u &= t
print u, s, t

结果:

set(['a', 'c', 'b']) set(['a', 'c', 'b']) set(['c', 'b', 'd'])

set(['c', 'b']) set(['c', 'b']) set(['c', 'b', 'd'])

按位运算符 &=(不改变s):

s = 7
t = 3
u=s
print u, s, t
u &= t
print u, s, t

结果:

7 7 3

3 7 3

7
集合是可变的,而整数则不是。使用frozenset尝试一下。 - jonrsharpe
它与frozensets一起按预期工作。因此,该操作并未尝试就地修改集合u(语句开头与s为同一对象),否则将会导致异常。它到底在尝试做什么? - M. Bailey
列表在 &= 方面表现与集合相同。元组会导致 TypeError。 - M. Bailey
是的,列表也是可变的。而元组则不是。 - jonrsharpe
Frozensets不可变,但不会导致类型错误。 &=对于可变和不可变类型的行为在哪里记录? - M. Bailey
如果我在两个列表上使用&=,会得到一个TypeError。 - Alex Hall
1个回答

5
整数实现了 & 操作,但没有实现 &= 操作,因此当您使用 x &= y 时,它会被扩展为 x = x & y,这只是重新分配 x 变量而不是修改其内部状态(对于 & 来说,改变值的状态并没有太多意义,就像对于 + 也没有太多意义)。对于 frozensets 也是如此。
集合实现了 &= 操作,因此它不会被扩展为变量重新分配,而是改变操作符左侧的状态。
元组既不实现 &,也不实现 &=,因此出现错误是有道理的。但是您可以通过 += 实现相同的效果:对于元组,+= 被扩展了,对于列表,它是一个就地变异,因为列表是可变的。
任何类都可以实现自己版本的这些运算符。详情请参见此处。特别地,& 对应于 __and__&= 对应于 __iand__
如果您仔细思考一下,对于可变类来说,实现原地操作符以允许直接修改是一个明智的约定,但不适用于不可变类。

谢谢。你给了我足够的信息,让我在Python 2.7.11文档中找到了“增强赋值”(Augmented Assignment)、PEP-203和我的答案,网址是https://docs.python.org/2/reference/simple_stmts.html。 - M. Bailey

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接