[英]Python collections.Counter, how to avoid double lookup
尝试在这里学习python:
假设我有一个非常大的 Counter 对象,如果该值大于 0,我想在其中更改特定键的值。所以是这样的:
from collections import Counter
...
A = Counter(huge_list)
...
if (A[some_key] > 0):
...
A[some_key] -= 1
...
...
我的问题是,如何避免对相同值 A[some_key] 进行双重查找? 例如,在 C++ 中发生的方式是返回对 A[some_key] 的引用,然后更改该引用指向的值,所以可能是这样的:
#include <iostream>
#include <string>
#include <map>
using namespace std;
int main()
{
map<string, int> A = { {"key", 1}, {"key2", 2}};
int &a = A["key"];
if ( a > 0 ) {
a--;
}
cout << A["key"] << endl;
}
这将很高兴地打印 0。
我相信这里的问题是 Counter 的值是不可变的对象; 正在做:
a = A[some_key]
“a”将是对对象 A[some_key] 的引用。 但随后的:
a-=1
将简单地将“a”分配给另一个具有相同值减一的 int 对象,并且 A[some_key] 将保持不变。
我想一种解决方案是使用一个值为单个整数列表的 defaultdict; 列表是可变的,因此我可以删除整数值并插入一个递减 1 的新值,这次 A[some_key] 会改变。 但是有更好的方法吗?
这可能也意味着我在此处描述的问题对于每个可迭代的不可变对象集合都应该是常见的?
你怎么看?
您可以通过使用max(0, ...)
而不是if ... > 0: ...
来避免三种查找之一。
>>> def f(c):
... if c['a'] > 0:
... c['a'] -= 1
>>> def g(c):
... c['a'] = max(0, c['a'] - 1)
>>> import dis
>>> dis.dis(f)
2 0 LOAD_FAST 0 (c)
2 LOAD_CONST 1 ('a')
4 BINARY_SUBSCR
6 LOAD_CONST 2 (0)
8 COMPARE_OP 4 (>)
10 POP_JUMP_IF_FALSE 28
3 12 LOAD_FAST 0 (c)
14 LOAD_CONST 1 ('a')
16 DUP_TOP_TWO
18 BINARY_SUBSCR
20 LOAD_CONST 3 (1)
22 INPLACE_SUBTRACT
24 ROT_THREE
26 STORE_SUBSCR
28 LOAD_CONST 0 (None)
30 RETURN_VALUE
>>> dis.dis(g)
2 0 LOAD_GLOBAL 0 (max)
2 LOAD_CONST 1 (0)
4 LOAD_FAST 0 (c)
6 LOAD_CONST 2 ('a')
8 BINARY_SUBSCR
10 LOAD_CONST 3 (1)
12 BINARY_SUBTRACT
14 CALL_FUNCTION 2
16 LOAD_FAST 0 (c)
18 LOAD_CONST 2 ('a')
20 STORE_SUBSCR
22 LOAD_CONST 0 (None)
24 RETURN_VALUE
BINARY_SUBSCR
读取c['a']
并且STORE_SUBSCR
分配给c['a']
。
这是Python 3.8.1 (tags/v3.8.1:1b293b6, Dec 18 2019, 23:11:46) [MSC v.1916 64 bit (AMD64)] on win32
使用Python 3.8.1 (tags/v3.8.1:1b293b6, Dec 18 2019, 23:11:46) [MSC v.1916 64 bit (AMD64)] on win32
。
但这并不意味着其中一个版本更快。 您必须进行一些测量才能找到答案。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.