你为什么感到惊讶?
您知道“增强分配”这个术语,所以找到"Python Data Model on augmented arithmetic assignments"(强调我的)没有问题:
这些 [__i***__] 方法应该尝试就地执行操作(修改 self)并返回结果(可以是但不一定是 self)。 如果未定义特定方法,则扩充分配回退到普通方法。例如,如果 x 是具有 __iadd__() 方法的类的实例,则 x += y 是相当于 x = x.__iadd__(y) 。否则,考虑x.__add__(y) 和y.__radd__(x),[...]
>>> x = frozenset(['foo', 'bar', 'baz'])
>>> x.__iand__
[...]
AttributeError: 'frozenset' object has no attribute '__iand__'
所以它没有__iand__ 方法所以你执行的代码是:
>>> x = x & {'baz', 'qux', 'quux'}
__and__ 方法是由 frozenset 定义的:
>>> x & {'baz', 'qux', 'quux'}
frozenset({'baz'})
但是你失去了对原始frozenset的引用:x:
>>> y = x # that doesn't do a copy, it's just to check if `x` has changed"
>>> x &= {'baz', 'qux', 'quux'}
>>> x is y # check if they reference the same object!
False
>>> x, y
(frozenset({'baz'}), frozenset({'bar', 'baz', 'foo'}))
但这只是在"Principle of least astonishment" 之后。您想要 __and__ 并且明确表示您不想保留原来的 x - 就地操作也会改变它!
再说一遍:为什么这让你感到惊讶?