13

有没有办法对测试为 has_key() 的字典进行三元运算而不会遇到关键错误?IE

variable = dict["the_key"] if dict.has_key("the_key") else "something"

(这显然是关键错误)

如果做不到这一点,根据可能有或没有相关键的 dict 分配一堆变量值的最 Pythonic 方法是什么?重复:

if dict.has_key('key'):
    value = dict['key']
else:
    value = "value"

ad nauseum 似乎很不雅。

4

5 回答 5

14

这:

mydict.get(key, default_value)

不是 100% 与立即评估的相同,default_valueelse仅在满足条件时才评估零件。

于 2012-12-03T20:19:12.743 回答
13

Jochen Ritzel 的回答是 99.9999% 的正确方法:

variable = d.get("the key", "something")

正如他所指出的,它不允许您短路默认值的评估。你通常不在乎。它的默认值是"something",你当然不知道。仅当默认值是危险的或非常昂贵的生成时才重要。

只有在这种情况下,您才能并且应该使用您的想法。除了你想要in而不是has_key(因为它更具可读性,更快,并且不被弃用):

variable = d["the key"] if "the key" in d else expensiveComputation()

但是,使用if语句而不是三元表达式可能值得,因为您避免使用的事实很expensiveComputation重要,并且您希望它更明显:

if "the_key" in d:
    variable = d["the key"]
else:
    variable = expensiveComputation()

如果您希望默认情况很少见,则更好:

try:
    variable = d["the key"]
except KeyError:
    variable = expensiveComputation()

如果由于某种原因您需要避免两次查找密钥,并且您也无法处理异常,并且您需要一次短路默认值:

sentinel = object()
variable = d.get(sentinel)
if variable == sentinel:
    variable = expensiveComputation()

是的,您可以将所有这些都包装在一个函数中,这样它就可以成为一个单行代码,但是您几乎肯定不想隐瞒您同时做三件罕见的事情的事实。

或者,当然,你可以这样做:

d = collections.defaultdict(expensiveComputation)

然后,它只是:

variable = d["the key"]

这具有在返回给您之前设置d["the key"]为的副作用,因此稍后调用将返回相同的值。如果这听起来合适,这是最好的答案;如果您永远不会使用相同的密钥两次,或者这些东西很大而且很浪费,等等,这是一个坏主意。expensiveComputation()d["the key"]

或者,或者,您可以覆盖该dict.__missing__方法而不是使用defaultdict

class MyDict(dict):
    def __missing__(self, key):
        return expensiveComputation()

然后,再次,它只是:

variable = d["the key"]

当您希望每次都单独生成值而不是将其保留以供以后使用时,此选项是合适的。

于 2012-12-03T20:36:37.590 回答
3

使用 .get() 方法 - 如果密钥不存在,它将返回 None ,或者您可以设置自己的默认值:

http://docs.python.org/2/library/stdtypes.html#dict.get

value = mydict.get("key", "default")
于 2012-12-03T20:21:18.190 回答
1

variable = d['the_key'] if 'the_key' in d else 'something'

于 2012-12-03T20:19:32.167 回答
0
value = 'value'
if 'key' in dict:
   value = dict['key']

或定义一个默认值

dict.get('key', 'value')

于 2012-12-03T20:19:30.513 回答