有没有比dict.get更好的东西(<thing>,dict.get(<other>))?</other> </thing>

时间:2014-03-07 20:15:08

标签: python dictionary

在Python中,

>>> x = {'spam': 'a lot'}
>>> x.get('eggs', x.get('spam'))
'a lot'

.get()组合似乎很尴尬。

有没有更好的方式说,“这可能是两个关键之一,我不在乎哪个,只是给我价值”?

5 个答案:

答案 0 :(得分:4)

我能想到的最“正确”的解决方案也是最丑陋的。太糟糕了。我的两个标准:

  • 避免0 or None角落案件
  • 如果存在一个密钥则短路

尽管它很丑陋,但这实际上是最快的执行:

x['eggs'] if 'eggs' in x else x.get('spam')

timeit结果:

>>> op       = lambda: x.get('eggs', x.get('spam'))
>>> aaron    = lambda: x.get('eggs') or x.get('spam')
>>> ndpu     = lambda: filter(None, map(x.get, ['eggs', 'spam']))[0]
>>> mhlester = lambda: x['eggs'] if 'eggs' in x else x.get('spam')
>>>
>>> timeit(op, number=100000)
0.04057041245972073
>>> timeit(aaron, number=100000)
0.04477326960257777
>>> timeit(ndpu, number=100000)
0.13210876799140614
>>> timeit(mhlester, number=100000)
0.03425499248118058

答案 1 :(得分:1)

我想我会倾向于这样做,因为它可能更具可读性:

>>> x = {'spam': 'a lot'}
>>> results = x.get('eggs') or x.get('spam')
>>> results
'a lot'

您的代码看起来实际上效率更高,但它必须评估这两个函数,因此or的快捷方式实际上效果更好。

这可能不符合您的意图,如果x ['eggs']返回一个空值,请注意该行为(但您确实说过,您不介意获取任何一个值):

>>> results = 0 or 'a lot'
>>> results
'a lot'
>>> results = '' or 'a lot'
>>> results
'a lot'

意想不到的角落案例可能是这样的:

>>> results = '' or None
>>> print(results)
None

答案 2 :(得分:1)

如果你只是在寻找一个单行,我相信已经发布的三元包含它:

result = myDict['eggs'] if 'eggs' in myDict else myDict.get('spam')

如果您只是在寻找可读的答案,我想您只需要if声明。

result = myDict.get('eggs', 'fail')
if result == 'fail':
    result = myDict.get('spam')

有什么不利于像这样分手吗?

答案 3 :(得分:1)

我喜欢Stick的答案,但如果你要做的事情超过两次(遵循“三规则”),我会将它包装在一个课程中。 另外:速度不应该是第一个问题 - 除非实际需要。简单易懂。

class MyDict(dict):
    def get(self, first_key, second_key, default=None):
        if first_key in self:
            return self[first_key]
        elif second_key in self:
            return self[second_key]
        else:
            return default

x = MyDict({"spam":"a lot"})
print x.get("eggs","spam")
# "a lot"    

答案 4 :(得分:-1)

mapfilter

>>> x = {'spam': 'a lot'}
>>> filter(None, map(x.get, ('eggs', 'spam'))) # [0]
['a lot']

列表理解:

>>> [x.get(k) for k in ('eggs', 'spam') if k in x]
['a lot']
当需要检查两个以上的密钥时,

非常有用:

>>> filter(None, map(x.get, ('eggs', 'foo', 'bar', 'spam')))
['a lot']