Python 如果键存在,则可以作为默认参数调用dict.get而不调用它

Python 如果键存在,则可以作为默认参数调用dict.get而不调用它,python,dictionary,Python,Dictionary,我试图提供一个函数作为字典的get函数的默认参数,如下所示 def run(): print "RUNNING" test = {'store':1} test.get('store', run()) 但是,在运行时,它会显示以下输出: RUNNING 1 因此,我的问题是,正如标题所说,是否有一种方法可以提供一个callable作为get方法的默认值,而不在键存在时调用它?请参阅的答案和注释中的讨论。你必须把它分成两个步骤 你的选择是: 如果您始终希望将该值作为默认值,并希望

我试图提供一个函数作为字典的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()
    
  • 以及这些主题的变化

    GLGL显示了一种将
    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,感谢它的简短和甜蜜。完美的