【问题标题】:Why are set methods like .intersection() not supported on set-like objects?为什么类似集合的对象不支持像 .intersection() 这样的集合方法?
【发布时间】:2019-04-05 06:25:11
【问题描述】:

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

.keys() 产生一个类似集合的对象,但是大多数集合方法都不能处理它。然而,有效的是类集合对象的极其未知的按位运算符重载,例如&

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 种。

【问题讨论】:

  • 如果您担心过于冗长,则无需在最后一个示例中将n.keys 转换为setset(m.keys()).intersection(n.keys())
  • 虽然不同意应该支持方法以符合预期的一般观点,但我发现各种运算符的重载相当直观,并且更喜欢它们而不是过于冗长(并且经常令人困惑)的名称方法。我知道所有按位运算符的作用类似于它们对位的作用。 ^ 立即有意义,但 symmetric_difference 总是需要一些时间来注册; <<= 马上就清楚了,但 issubset 模仿的是哪个不是。
  • @sacul:就此而言,您无需致电.keys()set(m).intersection(n) 将等效地工作,因为 dicts 已经像他们自己的值的唯一迭代一样。打扰.keys()唯一 原因是获得类似集合的行为;如果您无论如何要转换为set,则不需要它。
  • @ShadowRanger 所以你说最干净的代码实际上是:set(m).intersection(n),对吧?
  • @hyperknot:或者只是m.keys() & n.keys()(实际上,m.keys() & n 也可以正常工作,但让它像那样不对称感觉很奇怪)。

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


【解决方案1】:

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 不需要命名方法,可能是因为它们有点复杂(大多数采用可变参数,可变参数可以是任何可迭代的,而不仅仅是其他集合- 类似的东西,所以你可以,例如,intersection 一次有许多迭代),他们可能想要限制实现新子类(尤其是虚拟子类,不会继承任何方法)所需的复杂性@ 987654338@可能会选择提供)。

说了这么多,我基本同意你的观点,即省略方法形式似乎不必要地不一致。我建议您在 the Python bug tracker 上打开一个错误请求更改;仅仅因为它只保证Set的兼容性并不意味着它不能做更多。

【讨论】:

    【解决方案2】:

    格式应该是

    set.intersection(*others)
    

    其中 other 是任何可迭代的。 m.keys() 是 dict_keys 不是一个集合,所以它不起作用。

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

    会工作:)

    【讨论】:

      猜你喜欢
      • 2013-02-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-17
      • 1970-01-01
      • 1970-01-01
      • 2018-01-15
      • 2021-12-10
      相关资源
      最近更新 更多