集合操作:应该仅与集合一起使用,但可以与dict_keys一起使用?

发布于 2025-01-24 03:06:08 字数 1507 浏览 4 评论 0原文

set Operations的文档>

请注意,Union(),bettrosection()的非操作版本, 差异(),symmetric_difference(),issubset()和issuperset() 方法将接受任何觉得作为参数。相反,他们 基于操作员的同行要求将其参数设置为设置。这 排除诸如set('abc')& amp; amp; amp; amp; amp; amp;排除了。 'CBS'支持 更可读的set('abc')。交叉点('cbs')

通过以下实验对此进行测试:

# Python 3.10.2 (main, Jan 15 2022, 19:56:27) [GCC 11.1.0] on linux

>>> set('ab') & set('ac')
{'a'}
# works, as expected

>>> set('ab') & 'ac'
TypeError: unsupported operand type(s) for &: 'set' and 'str'
# doesn't work, as expected

>>> set('ab') & list('ac')
TypeError: unsupported operand type(s) for &: 'set' and 'list'
# doesn't work, as expected

>>> set('ab') & iter('ac')
TypeError: unsupported operand type(s) for &: 'set' and 'str_iterator'
# doesn't work, as expected

>>> set('ab') & dict(zip('ac', 'ac')).keys()
{'a'}
# works??

>>> type({}.keys())
<class 'dict_keys'>

>>> isinstance({}.keys(), (set, frozenset))
False

因此,这是悖论:

  • set操作员&amp;dict_keys对象一起工作;
  • 该文件说,它只能与集合一起使用;
  • dict_keys未设置对象。

为什么设置运算符&amp;与dict_keys对象一起工作?它还有其他类型吗?我如何找到这些类型的列表?

The documentation for set operations says:

Note, the non-operator versions of union(), intersection(),
difference(), symmetric_difference(), issubset(), and issuperset()
methods will accept any iterable as an argument. In contrast, their
operator based counterparts require their arguments to be sets. This
precludes error-prone constructions like set('abc') & 'cbs' in favor
of the more readable set('abc').intersection('cbs').

Testing this with the following experiment:

# Python 3.10.2 (main, Jan 15 2022, 19:56:27) [GCC 11.1.0] on linux

>>> set('ab') & set('ac')
{'a'}
# works, as expected

>>> set('ab') & 'ac'
TypeError: unsupported operand type(s) for &: 'set' and 'str'
# doesn't work, as expected

>>> set('ab') & list('ac')
TypeError: unsupported operand type(s) for &: 'set' and 'list'
# doesn't work, as expected

>>> set('ab') & iter('ac')
TypeError: unsupported operand type(s) for &: 'set' and 'str_iterator'
# doesn't work, as expected

>>> set('ab') & dict(zip('ac', 'ac')).keys()
{'a'}
# works??

>>> type({}.keys())
<class 'dict_keys'>

>>> isinstance({}.keys(), (set, frozenset))
False

So, here is the paradox:

  • set operator & works with dict_keys objects;
  • The documentation says it should only work with sets;
  • dict_keys objects are not sets.

Why does set operator & work with dict_keys objects? Are there other types that it works with? How can I find a list of these types?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

对岸观火 2025-01-31 03:06:08

这不是一个完整的答案,但是dict_keys collections.abc.set

from collections.abc import Set
k = dict(zip('ac', 'ac')).keys()
print(isinstance(k, Set))  # -> True

this is not a complete answer, but dict_keys are instances of collections.abc.Set:

from collections.abc import Set
k = dict(zip('ac', 'ac')).keys()
print(isinstance(k, Set))  # -> True
电影里的梦 2025-01-31 03:06:08

文档的这一部分是指set/frozenset类型支持。确实,set不支持与dict_keys实例的比较,并且它正确返回

>>> left = set('ab')
>>> right = dict(zip('ac', 'ac')).keys()
>>> left.__and__(right)
NotImplemented

​。它成功:

>>> right.__rand__(left)
{'a'}

如果 类型(左).__和__type(右)。 ,然后您将看到typeerror异常。

因此,没有悖论,只有数据模型中的一个微妙之处:set选择退出,dict_keys类型有机会从右手处理二进制操作边。

This section of the docs is referring to what the set/frozenset types support. Indeed, set does not support the comparison with dict_keys instances, and it correctly returns NotImplemented to indicate this operation is unsupported:

>>> left = set('ab')
>>> right = dict(zip('ac', 'ac')).keys()
>>> left.__and__(right)
NotImplemented

This return value indicates that Python should attempt the reflected operation with the other operand, to see if that is supported. And it succeeds:

>>> right.__rand__(left)
{'a'}

If both type(left).__and__ and type(right).__rand__ are returning NotImplemented, then you will see a TypeError exception.

So, there is no paradox, just a subtlety in the datamodel: after set opts out, the dict_keys type is afforded the chance to handle the binary operation from the right-hand side.

鲜肉鲜肉永远不皱 2025-01-31 03:06:08

(没有足够的代表来发表评论)

设置运算符也可以在dict_keys和列表之间工作。
但是由于某种原因而不是在集合和列表之间似乎不一致

Python 3.10.12 (main, Sep 11 2024, 15:47:36) [GCC 11.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> s = {1, 2}
>>> d = {2:0, 3:0}
>>> l = [3, 4]
>>> s - d.keys()
{1}
>>> d.keys() - s
{3}
>>> d.keys() - l
{2}
>>> l - d.keys()
{4}
>>> s -l
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for -: 'set' and 'list'
>>> l - s
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for -: 'list' and 'set'

(don't have enough rep. to comment)

The set operators also work between dict_keys and lists.
But for some reason not between sets and lists which seems inconsistent

Python 3.10.12 (main, Sep 11 2024, 15:47:36) [GCC 11.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> s = {1, 2}
>>> d = {2:0, 3:0}
>>> l = [3, 4]
>>> s - d.keys()
{1}
>>> d.keys() - s
{3}
>>> d.keys() - l
{2}
>>> l - d.keys()
{4}
>>> s -l
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for -: 'set' and 'list'
>>> l - s
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for -: 'list' and 'set'
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文