我有以下代码:
import json
stats = dict()
for line in input : # many many lines
for (field,value) in json.loads(line).iteritems() :
stats.get(field,very_expensive_initializer(field)).add(value)
问题在于Python并不懒惰,因此对于每行中的每个字段都调用一次
very_expensive_initializer
,而不是为每个字段调用一次。对?避免这种情况的正确方法是什么?
例如,这足够惯用吗?
try : s = stats[field]
except KeyError : s = stats[field] = very_expensive_initializer(field)
s.add(value)
最佳答案
如果默认值昂贵,请测试密钥:
item = stats.get(field) or very_expensive_initializer(field)
item.add(value)
或者
stats[field]
可能为空:item = stats[field] if field in stats else very_expensive_initializer(field)
item.add(value)
or
和条件表达式的计算都比较延迟。您仍然可以将其设置为单线,但是我不确定您应该这样做。上面的代码与您的原始代码匹配。
请注意,这不会将
very_expensive_initializer(field)
添加到stats
!您也可以这样做:if field not in stats:
stats[field] = very_expensive_initializer(field)
要么
try:
item = stats[field]
except KeyError:
item = stats[field] = very_expensive_initializer(field)
如果通常在
field
中找不到stats
,则选择第一个;如果偶尔仅在field
中找不到stats
,则选择后者。您的下一个选择是
dict
的子类并添加__missing__
方法:class subclassed_dict(dict):
def __missing__(self, key):
item = self[key] = very_expensive_initializer(key)
return item
然后将其用作
stats
:stats = subclassed_dict()
每当您尝试访问尚不存在的密钥时,Python都会调用
__missing__
。演示:
>>> def very_expensive_initializer(field):
... print 'Doing loads of work'
... return set()
...
>>> class subclassed_dict(dict):
... def __missing__(self, key):
... item = self[key] = very_expensive_initializer(key)
... return item
...
>>> stats = subclassed_dict()
>>> stats['foo'].add(2)
Doing loads of work
>>> stats['foo'].add(3)
>>> stats['foo'].add(4)
>>> stats['bar']
Doing loads of work
set([])
>>> stats['bar']
set([])
关于python - 如何在字典中初始化值?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/20379435/