为什么collections.MutableSet不提供更新方法?

Tha*_*tos 3 python collections set mixins

当实现一个类似于set的类时,可以继承collections.MutableSet,如果你实现了他们需要的方法,它将赋予新类几个mixin方法.(换句话说,集合中的一些方法可以用其他方法实现.为了避免这种无聊,collections.MutableSet朋友只包含那些实现.)

文档说抽象方法是:

__contains__,__iter__,__len__,add,discard

而且mixin方法是

继承Set方法和clear,pop,remove,__ior__,__iand__,__ixor__,和__isub__

(并且,为了清楚这update不是"继承Set方法Set"的一部分,mixin方法是:

__le__,__lt__,__eq__,__ne__,__gt__,__ge__,__and__,__or__,__sub__,__xor__,和isdisjoint

但是,Set指的是一个自然不会有的不可变集update.)

为什么update不在这些方法中呢?我发现它令人惊讶 - 甚至不直观 - set包含这种方法,但却collections.Set没有.例如,它会导致以下情况:

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'
Run Code Online (Sandbox Code Playgroud)

或许更奇怪的是,MutableMapping 它确实赋予了一种update方法,而MutableSet不是.AFAICT,源代码没有提到任何原因.

Ray*_*ger 6

MutableSet的API 由Guido van Rossum设计.他的提议在PEP 3119关于集合的部分中有所阐述.没有详细说明,他指出:

"这个类还定义了用于计算并集,交集,对称和非对称差异的具体运算符,分别为__or __,__ and__,__ xor__和__sub__"

...

"这也支持就地变异操作| =,&=,^ =, - =.这些是具体的方法,其右操作数可以是任意的Iterable,除了&=,其右操作数必须是一个Container.这个ABC不提供执行(几乎)相同操作的内置混凝土集类型中存在的命名方法.

这里没有错误或疏忽; 相反,对于你是否喜欢Guido的设计存在一些意见.

Python禅宗有话要说:

  • 应该有一个 - 最好只有一个 - 明显的方法来做到这一点.
  • 虽然这种方式起初可能并不明显,除非你是荷兰人.

也就是说,抽象基类的设计很容易扩展.使用自己的update()方法添加自己的update()方法是微不足道的update = Set.__ior__.