从可能缺失的字典值初始化Python变量

1 投票
4 回答
1990 浏览
提问于 2025-04-16 18:38

用Python的方式怎么做这个比较好呢?

value = (mydict.has_key('index') and mydict['index']) or 1024

从字典的值初始化,如果有的话;如果没有,就用默认值。

我在网上看到一些关于LBYL和EAFP的回答,但代码写得太复杂了 :p

我想要一种一行就能初始化的写法。

附注:只支持python-2.4(我在用CentOS5)

4 个回答

1

了解 getsetdefault 方法非常重要,它们应该是每个 Python 程序员工具箱里的必备工具。

还有一种很重要的方法就是使用 collections.defaultdict,这样你可以在一个地方定义你的“默认值”,而不需要在代码中到处散布这个默认值,也就是避免重复代码。如果你需要更改默认值,就不需要到处去找那些 getsetdefault 的调用了。例如:

>>> import collections
>>> myDict = collections.defaultdict
>>> myDict = collections.defaultdict(lambda : 1024)
>>> myDict[0] += 1
>>> print myDict[0], myDict[100]
1025 1024

因为你可以设置函数调用,所以你可以为默认值做任何你想做的事情。比如说,为每个新键分配一个 1 到 10 之间的随机值怎么样?

>>> import collections
>>> import random
>>> myDict = collections.defaultdict(lambda : random.randint(1,10))
>>> print myDict[0], myDict[100]
1 5
>>> print myDict[0], myDict[100], myDict[2]
1 5 6

好吧,这个例子有点牵强,但我相信你能想到更好的用法。假设你有一个构造起来很费资源的类——只有在键不存在时,实例才会被创建,这和调用 getsetdefault 不一样,例如:

>>> class ExpensiveClass(object):
>>>     numObjects = 0
>>>     def __init__(self):
>>>         ExpensiveClass.numObjects += 1
>>> 
>>> print ExpensiveClass.numObjects
0
>>> x = {}
>>> x[0] = ExpensiveClass()
>>> print ExpensiveClass.numObjects
1
>>> print x.get(0, ExpensiveClass())
<__main__.ExpensiveClass object at 0x025665B0>
>>> print ExpensiveClass.numObjects
2
>>> ExpensiveClass.numObjects = 0
>>> z = collections.defaultdict(ExpensiveClass)
>>> print ExpensiveClass.numObjects
0
>>> print z[0]
>>> <__main__.ExpensiveClass object at 0x02566510>
>>> print ExpensiveClass.numObjects
1

注意,调用 x.get 会构造一个新的 ExpensiveClass 实例,即使我们根本不使用这个实例,因为 x[0] 已经存在了。如果你确实想要计算 ExpensiveClass 对象的数量,或者它们的创建速度非常慢,这可能会造成问题。而使用 collections.defaultdict 就不会出现这些问题。

2

另外,你可以使用 setdefault() 这个方法。它的作用和 get() 类似,不过在返回值之前,它会先插入这个键。

value = mydict.setdefault('index', 1024)
11
value = mydict.get('index', 1024)

(注意,这个和你的代码不完全一样,因为它只会在键 index 不存在时使用 1024,而你的代码在键 index 对应的值是假的时候也会使用 1024。从你的解释来看,我推测你其实想要的是前者。)

撰写回答