Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/276.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 还有比dict.get(<;thing>;、dict.get(<;other>;)更好的吗?_Python_Dictionary - Fatal编程技术网

Python 还有比dict.get(<;thing>;、dict.get(<;other>;)更好的吗?

Python 还有比dict.get(<;thing>;、dict.get(<;other>;)更好的吗?,python,dictionary,Python,Dictionary,在Python中 >>> x = {'spam': 'a lot'} >>> x.get('eggs', x.get('spam')) 'a lot' 但是,.get()组合似乎有些尴尬 有没有更好的方法可以说,“这可能是两个键中的一个,我不在乎哪个键,只要给我值就行了”我想我会这样做,因为它可能更具可读性: >>> x = {'spam': 'a lot'} >>> results = x.get('eggs') or

在Python中

>>> x = {'spam': 'a lot'}
>>> x.get('eggs', x.get('spam'))
'a lot'
但是,
.get()
组合似乎有些尴尬


有没有更好的方法可以说,“这可能是两个键中的一个,我不在乎哪个键,只要给我值就行了”

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

>>> x = {'spam': 'a lot'}
>>> results = x.get('eggs') or x.get('spam')
>>> results
'a lot'
您的代码看起来实际上效率更高,但它必须同时评估这两个函数,因此使用
进行简化实际上效果更好

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

意外情况可能是这样的:

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

使用
映射
过滤器

>>> 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']
我能想出的最“正确”的解决方案也是最丑陋的。那太糟糕了。我的两个标准是:

  • 避免出现
    0或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

如果你只是在寻找一个单一的班轮,我相信已经发布的三元涵盖了它:

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

如果您只是在寻找可读的答案,我想您只需要使用
If
语句

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

像这样分手有什么不好的地方吗?

我喜欢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"    


但是如果
x['eggs']
0
,该怎么办?我想要
0
,而不是
None
至于效率,你的效率实际上更高,因为它会短路。函数在调用之前需要计算所有参数,因此
get
s都保证在您的函数中被调用。@mhlester:或者更糟的是,您可能会得到
“很多”
!没错,对于x['eggs']=0,它可能会产生意想不到的结果,我会记下来。正如@mhlester所说,它实际上更快,而且更容易阅读。我建议改为使用defaultdict。这种模式有奇怪的副作用,我自己也从未想过要使用这种模式。@davidermann:defaultdict
如何用于此?OP的版本带来了什么奇怪的副作用?@JohnY这感觉像是一种默认模式(虽然可能不是),因此是默认模式。副作用是,改变
x[“垃圾邮件”]
会改变get的行为。@davidermann:嗯,OP真正想做的是(1)尝试“鸡蛋”,如果这不起作用,尝试“垃圾邮件”,如果不起作用,则获得
None
;或者(2)获取“鸡蛋”或“垃圾邮件”,不管是哪一个,如果两者都失败,则获取
None
。对于
defaultdict
您将使用哪个工厂函数来获取这些行为?如果您不介意将
d['spam']
的值写入
d['eggs']
除了返回它之外,您还可以执行类似
d=defaultdict(partial(d.get,'spam'))的操作。
…嗯?这有什么帮助?为什么您要“注释”第一个示例中的
[0]
,而不在第二个示例中包含它?除了这些问题之外,我确实认为这个答案很有用,以防有许多可能的键需要检查。为了完整性,还值得注意的是,这可以通过列表理解而不是
map
filter
@JohnY空列表得到结果,所以我认为最好不要使用
[0]
使用此方法实现多功能性。。。如果
需要,我明白你关于空箱子的观点;但是如果没有索引,您可能会得到多个结果。最后,我想你确实需要做更多的检查来真正获得正确的功能。除了你的版本是唯一一个可以引发异常的版本。编辑。它比以前的
get
花费的时间长了50%,但对于简洁来说,它仍然是最快的+1。但速度不应该是决定因素,除非需要达成一致。我最喜欢的仍然是OP,尽管有更高的开销,不需要
myDict.get('eggs')
,因为如果您在代码的该部分,
'eggs'
已经确认在
myDict
中。这个答案与mhlester的答案类似,只是你还建议使用更长的形式,如果
myDict['egs']
实际上等于
'fail'
,那么这是不正确的。而且,
不是字符串相等性的正确测试。两个很长的字符串可以相等(使用
==
),但不能相同(使用
)。哦,是的,这很公平。我已经习惯了“我的值不是零”,所以我反过来应用了相同的值。哇。但希望大家能理解,“失败”值在理想情况下永远不会是“鸡蛋”的值——在这种情况下,人们不会使用鸡蛋式的值作为哨兵。我本打算驳回这个答案,但重新阅读OP的问题,我注意到他实际上并没有要求最短或最快的解决方案,只是一个“更好”的解决方案。如果反复使用,这肯定会更好。你甚至可以通过结合地图/过滤器或列表理解(如ndpu的答案)将其扩展到任意数量的键来检查。我一直在玩(一个变体)这个答案,我真的很喜欢它。根据OP的任务,这可能有点过分,但实现起来很容易。
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"