为什么类集对象不支持.intersection()这样的集方法?

时间:2018-11-01 02:09:59

标签: python python-3.x dictionary set dictview

在Python 3.7中,我想计算两个字典键的交集。为此,我想在其.intersection()上调用keys()方法,但是它不起作用。

.keys()会生成一个类似于set的对象,但是大多数set方法对此均不起作用。但是,对于&这样的集合对象,极其未知的按位运算符重载是有效的。

m = {'a':1, 'b':2}
n = {'b':3, 'c':4}

m.keys().intersection(n.keys())  # Pythonic, but doesn't work

m.keys() & n.keys()  # works but not readable

set(m.keys()).intersection(set(n.keys()))  # works, readable, but too verbose

我发现类似集合的对象上的&重载极少使用,大多数程序员都不知道。 .intersection().union()之类的方法名称是自记录的,并且根据此定义,其定义肯定更像Python。

为什么不支持它?甚至documentation都列出了&.intersection()这样的方法,例如别名,更不用说在类集合对象上仅支持&了。

注释:出于某种原因,在IPython中,自动完成列表将.isdisjoin()列为dict.keys()上可用的方法。在这17种设置方法中,有1种。

2 个答案:

答案 0 :(得分:2)

dict views only guarantee the API of collections.abc.Set,不等同于set本身:

  

对于类似集合的视图,为抽象基类collections.abc.Set定义的所有操作都是可用的(例如==<^)。

因此,他们并没有声称匹配set甚至是frozenset,而只是声称collections.abc.Set collections.abc.Set doesn't require any of the named methods aside from isdisjoint(没有等效的运算符)。

关于为什么 collections.abc.Set不需要命名方法,可能是因为它们有些复杂(大多数采用varargs,而varargs可以是任何可迭代的,而不仅仅是其他类似集合的东西,例如您可以同时intersection具有多个可迭代对象),并且它们可能想要限制实现新子类(尤其是虚拟子类,它不会继承任何子类)所需的复杂性collections.abc.Set的方法中可以选择提供)。

所有这些,我通常同意您的观点,即省略方法表格似乎是不必要的矛盾。建议您打开the Python bug tracker上的错误以请求更改;仅仅因为它仅保证Set的兼容性并不意味着它不能做更多的事情。

答案 1 :(得分:0)

格式应为

set.intersection(*others)

其他是可迭代的。 m.keys()不是dict_keys集合,因此无法正常工作。

set(m.keys()).intersection(n.keys())

将起作用:)