可调用作为dict.get的默认参数,如果密钥存在则不调用它

时间:2011-09-30 13:17:35

标签: python dictionary

我试图提供一个函数作为字典的get函数的默认参数,就像这个

def run():
   print "RUNNING"

test = {'store':1}
test.get('store', run())

但是,运行此选项时,它会显示以下输出:

RUNNING
   1

所以我的问题是,正如标题所说,有一种方法可以提供一个callable作为get方法的默认值,如果该键存在则不会被调用吗?

5 个答案:

答案 0 :(得分:9)

另一个选项,假设您不打算在字典中存储虚假值

test.get('store') or run()

在python中,or运算符不会计算不需要的参数(它会短路)

答案 1 :(得分:7)

请参阅dict.get() method returns a pointer的答案和评论中的讨论。你必须把它分成两步。

您的选择是:

  1. 如果总是希望将该值作为默认值,并且希望将其存储在defaultdict中,请使用dict与callable一起使用。

  2. 使用条件表达式:

    item = test['store'] if 'store' in test else run()
    
  3. 使用try / except

    try:
        item = test['store']
    except KeyError:
        item = run()
    
  4. 使用get

    item = test.get('store')
    if item is None:
        item = run()
    
  5. 这些主题的变化。

    glglgl显示了一种子类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。

答案 2 :(得分:2)

我想你只想在密钥不存在时才应用callable。

有几种方法可以做到这一点。 一种方法是使用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中保存可以返回适当值的callables。

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)

而是每当key: value对未明确添加{{1}}对时调用默认工厂。

答案 3 :(得分:0)

如果你只知道他可以在调用网站上获得的可调用内容,那么你可以继承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'

当可调用计算代价很高时,这可能是最有用的。

答案 4 :(得分:0)

我的项目中有一个A你好B+c de.txt目录utilqt.pygeneral.py等。在geom.py我有一堆python工具,如你需要的那个:

general.py

如果您想支持使用不同的args多次调用默认值,请添加# Use whenever you need a lambda default def dictGet(dict_, key, default): if key not in dict_: return default() return dict_[key]

*args, **kwargs