Python 如果键存在,则可以作为默认参数调用dict.get而不调用它
我试图提供一个函数作为字典的get函数的默认参数,如下所示Python 如果键存在,则可以作为默认参数调用dict.get而不调用它,python,dictionary,Python,Dictionary,我试图提供一个函数作为字典的get函数的默认参数,如下所示 def run(): print "RUNNING" test = {'store':1} test.get('store', run()) 但是,在运行时,它会显示以下输出: RUNNING 1 因此,我的问题是,正如标题所说,是否有一种方法可以提供一个callable作为get方法的默认值,而不在键存在时调用它?请参阅的答案和注释中的讨论。你必须把它分成两个步骤 你的选择是: 如果您始终希望将该值作为默认值,并希望
def run():
print "RUNNING"
test = {'store':1}
test.get('store', run())
但是,在运行时,它会显示以下输出:
RUNNING
1
因此,我的问题是,正如标题所说,是否有一种方法可以提供一个callable作为get方法的默认值,而不在键存在时调用它?请参阅的答案和注释中的讨论。你必须把它分成两个步骤 你的选择是:
dict
中,请将defaultdict
与callable一起使用item = test['store'] if 'store' in test else run()
尝试
/但
除外:
try:
item = test['store']
except KeyError:
item = run()
get
:
item = test.get('store')
if item is None:
item = run()
defaultdict
子类化的方法,在某些情况下,您也可以将dict
子类化:
def run():
print "RUNNING"
return 1
class dict_nokeyerror(dict):
def __missing__(self, key):
return run()
test = dict_nokeyerror()
print test['a']
# RUNNING
# 1
子类化只有在您总是希望
dict
具有一些非标准行为时才真正有意义;如果您通常希望它像普通的dict
一样工作,并且只希望在一个地方有一个惰性的get
,请使用我的方法2-4中的一个。我想您只希望在键不存在的情况下应用可调用
有几种方法可以做到这一点。
一种是使用defaultdict,如果缺少键,它将调用run()
from collections import defaultdict
def run():
print "RUNNING"
test = {'store':1}
test.get('store', run())
test = defaultdict(run, store=1) # provides a value for store
test['store'] # gets 1
test['runthatstuff'] # gets None
另一个相当丑陋的方法是,只在dict中保存返回适当值的callable
test = {'store': lambda:1}
test.get('store', run)() # -> 1
test.get('runrun', run)() # -> None, prints "RUNNING".
如果希望返回值取决于缺少的键,则必须将defaultdict子类化:
class mydefaultdict(defaultdict):
def __missing__(self, key):
val = self[key] = self.default_factory(key)
return val
d = mydefaultdict(lambda k: k*k)
d[10] # yields 100
@mydefaultdict # decorators are fine
def d2(key):
return -key
d2[5] # yields -5
如果您不想在下次通话时将此值添加到dict中,则有一个
def __missing__(self, key): return self.default_factory(key)
相反,它在每次未显式添加
键:值对时调用默认工厂。如果您只知道get调用站点上的可调用对象可能是什么,则可以将dict子类化为如下内容
class MyDict(dict):
def get_callable(self,key,func,*args,**kwargs):
'''Like ordinary get but uses a callable to
generate the default value'''
if key not in self:
val = func(*args,**kwargs)
else:
val = self[key]
return val
然后可以这样使用:-
>>> d = MyDict()
>>> d.get_callable(1,complex,2,3)
(2+3j)
>>> d[1] = 2
>>> d.get_callable(1,complex,2,3)
2
>>> def run(): print "run"
>>> repr(d.get_callable(1,run))
'2'
>>> repr(d.get_callable(2,run))
run
'None'
当可调用项的计算成本很高时,这可能最有用。另一个选项,假设您不打算在字典中存储错误值:
test.get('store') or run()
在python中,或
运算符不计算不需要的参数(它会短路)
如果您确实需要支持falsy值,则可以使用get\u或\u run(test,'store',run)
其中:
def获取或运行(d、k、f):
sentinel=object()#保证不在d中
v=d.get(k,哨兵)
如果v是sentinel else v,则返回f()
我的项目中有一个util
目录,其中包含qt.py
、general.py
、geom.py
等。在general.py
中,我有一系列python工具,如您需要的:
# Use whenever you need a lambda default
def dictGet(dict_, key, default):
if key not in dict_:
return default()
return dict_[key]
如果要支持使用不同的参数多次调用默认值,请添加*参数,**kwargs
:
def dictGet(dict_, key, default, *args, **kwargs):
if key not in dict_:
return default(*args, **kwargs)
return dict_[key]
这个问题没有意义。您询问的是默认参数,但您正在一个确实存在的键上尝试它-显然,get
将返回该键的值(如果该键存在)。你想达到什么目的?@DanielRoseman他的问题是,他如何让run
仅在值不存在时被调用,至于他当前的get
无论发生什么都会被调用。我澄清了他问题的最后一行。为什么首先调用run()
?有人会认为,除非需要,否则get()
不会为默认值操心。在dict
中围绕其所有数据创建lambda
s对于绝大多数实际情况来说听起来并不实用。不幸的是,defaultdict
在很多情况下也不起作用,在这些情况下,您不想在dict
中实际设置值,或者只想在某些情况下获得默认值。如果您对其进行子类化,它会起作用-请参见编辑后的第三个示例。这仍然将值存储在dict
中,这只是一个可以修改为不存储该值的示例:def\uuu missing\uuuu(self,key):返回self.default\u工厂(key)
。我想保持它接近原始的行为。->另一个edit如果您没有存储在dict
中,只需使用一个常规的dict
子类,并覆盖\uuuuuuuuuuuuuuuu
,而不是defaultdict
。我试图避免使用条件,但我认为使用defaultdict正是我所需要的,我将把GLGL的回答标记为被接受,因为他是第一个,但非常感谢:P,rly,感谢它的简短和甜蜜。完美的