When implementing a class that works like a set, one can inherit from collections.MutableSet
, which will bestow the new class with several mixin methods, if you implement the methods they require. (Said otherwise, some of the methods of a set can be implemented in terms of other methods. To save you from this boredom, collections.MutableSet
and friends contain just those implementations.)
The docs say the abstract methods are:
__contains__
,__iter__
,__len__
,add
,discard
and that the mixin methods are
Inherited
Set
methods andclear
,pop
,remove
,__ior__
,__iand__
,__ixor__
, and__isub__
(And, just to be clear that update
is not part of the "Inherited Set
methods, Set
's mixin methods are:
__le__
,__lt__
,__eq__
,__ne__
,__gt__
,__ge__
,__and__
,__or__
,__sub__
,__xor__
, andisdisjoint
However, Set
refers to an immutable set, which naturally would not have update
.)
Why is update
not among these methods? I find it surprising — unintuitive even — that set
contains this method, but collections.Set
does not. For example, it causes the following:
In [12]: my_set
Out[12]: <ms.MySet at 0x7f947819a5d0>
In [13]: s
Out[13]: set()
In [14]: isinstance(my_set, collections.MutableSet)
Out[14]: True
In [15]: isinstance(s, collections.MutableSet)
Out[15]: True
In [16]: s.update
Out[16]: <function update>
In [17]: my_set.update
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-17-9ed968a9eb18> in <module>()
----> 1 my_set.update
AttributeError: 'MySet' object has no attribute 'update'
Perhaps stranger is that MutableMapping
does bestow an update
method, while MutableSet
does not. AFAICT, the source code does not mention any reason for this.
The API for MutableSet was designed by Guido van Rossum. His proposal is articulated in PEP 3119's section on for Sets. Without elaboration, he specified that:
"This class also defines concrete operators to compute union, intersection, symmetric and asymmetric difference, respectively __or__, __and__, __xor__ and __sub__"
...
"This also supports the in-place mutating operations |=, &=, ^=, -=. These are concrete methods whose right operand can be an arbitrary Iterable, except for &=, whose right operand must be a Container. This ABC does not provide the named methods present on the built-in concrete set type that perform (almost) the same operations."
There is not a bug or oversight here; rather, there is a matter of opinion about whether you like or don't like Guido's design.
The Zen of Python has something to say about that:
That said, abstract base classes were designed to be easy to extend. It is trivial to add your own update() method to your concrete class with update = Set.__ior__
.