最近有一个问题,正确的答案真的让我很惊讶,在两个计数器上使用&
,然后"正确"。
From the docs:
计数器支持丰富的相等、子集和超集关系比较运算符:==、!=、<、<=、>、>=。所有这些测试都将缺失的元素视为计数为零,因此Counter(a=1) == Counter(a=1, b=0)返回true。
但这并没有涉及到&
的细节。我写了一个小测试脚本:
from collections import Counter
from pprint import pp
cls = Counter # `dict` fails: TypeError: unsupported operand type
o1 = cls(a=1,b=2,c=3,de=3,f=3,i1=9)
o2 = cls(a=1,b=2,c=3,de=5,f=6,i2=9)
res = o1 & o2
pp(dict(o1=o1,o2=o2,res=res))
输出为:
{'o1': Counter({'i1': 9, 'c': 3, 'de': 3, 'f': 3, 'b': 2, 'a': 1}),
'o2': Counter({'i2': 9, 'f': 6, 'de': 5, 'c': 3, 'b': 2, 'a': 1}),
'res': Counter({'c': 3, 'de': 3, 'f': 3, 'b': 2, 'a': 1})}
在我看来counter1 & counter2
的意思是:
- 计算两个键的交点 对于常用键的值,计算
min
我说的对吗?除了Counter
和set
之外,其他标准库数据结构是否也定义了__and__
(&
, IIRC的后台)?
你的理解非常正确。如果您从引用的地方往下看几行,您将看到&
在Counter
对象上的示例使用—您不需要深入到源代码中查找它:
交集和并集返回对应计数的最小值和最大值. ...
>>> c & d # intersection: min(c[x], d[x]) Counter({'a': 1, 'b': 1}) >>> c | d # union: max(c[x], d[x]) Counter({'a': 3, 'b': 2})
容器文档状态:
提供了几个数学运算来组合Counter对象以产生多集(计数大于0的计数器)。加法和减法通过增加或减少相应元素的计数来组合计数器。交集和并集返回对应计数的最小值和最大值。相等和包含比较相应的计数。每个操作都可以接受带符号计数的输入,但输出将排除计数为零或更小的结果。
回答你关于其他字典派生重写&
的问题,我认为没有。然而,set
(文档在这里)使用&
,|
,-
和^
来实现交集,并集,差和对称差。
根据官方文件:
>>> c = Counter(a=3, b=1) >>> d = Counter(a=1, b=2) >>> c + d # add two counters together: c[x] + d[x] Counter({'a': 4, 'b': 3}) >>> c - d # subtract (keeping only positive counts) Counter({'a': 2}) >>> c & d # intersection: min(c[x], d[x]) Counter({'a': 1, 'b': 1}) >>> c | d # union: max(c[x], d[x]) Counter({'a': 3, 'b': 2}) >>> c == d # equality: c[x] == d[x] False >>> c <= d # inclusion: c[x] <= d[x] False
还定义了一元操作:
>>> c = Counter(a=2, b=-4) >>> +c Counter({'a': 2}) >>> -c Counter({'b': 4})