Why are you surprised?
You knew the term "augmented assignment" so there is no problem finding the "Python Data Model on augmented arithmetic assignments" (emphasis mine):
These [__i***__
] methods should attempt to do the operation in-place (modifying self) and return the result (which could be, but does not have to be, self). If a specific method is not defined, the augmented assignment falls back to the normal methods. For instance, if x
is an instance of a class with an __iadd__()
method, x += y is equivalent to x = x.__iadd__(y)
. Otherwise, x.__add__(y)
and y.__radd__(x)
are considered, [...]
>>> x = frozenset(['foo', 'bar', 'baz'])
>>> x.__iand__
[...]
AttributeError: 'frozenset' object has no attribute '__iand__'
So it has no __iand__
method so the code you perform is:
>>> x = x & {'baz', 'qux', 'quux'}
The __and__
method however is defined by frozenset
:
>>> x & {'baz', 'qux', 'quux'}
frozenset({'baz'})
However you lost your reference to the original 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'}))
But that just follows the "Principle of least astonishment". You wanted the __and__
and you made it clear that you didn't want to keep your original x
- an in-place operation also would have altered it!
So again: Why did that surprise you?