什么是Pythonic这样做的方式?从可能缺失的字典值初始化Python变量
value = (mydict.has_key('index') and mydict['index']) or 1024
初始化从字典的值,如果存在的话,否则使用默认值。
上了车LBYL和EAFP一些答案,但过于冗长的代码:P
我想要一些单行初始化。
PS:蟒蛇 - 2.4只(运行CentOS5)
什么是Pythonic这样做的方式?从可能缺失的字典值初始化Python变量
value = (mydict.has_key('index') and mydict['index']) or 1024
初始化从字典的值,如果存在的话,否则使用默认值。
上了车LBYL和EAFP一些答案,但过于冗长的代码:P
我想要一些单行初始化。
PS:蟒蛇 - 2.4只(运行CentOS5)
value = mydict.get('index', 1024)
(请注意,这是不完全等同于你的代码,因为它会使用1024
只有在关键index
不存在,而你的代码还采用1024
当对应于关键index
值falsy从你的解释我推断前者是你真正想要什么)
需要注意的是,由于python是一种非惰性语言,因此将评估“默认值”表达式是否实际最终使用它。 (与if语句不同,它不会对它进行评估) – ninjagecko 2011-05-30 23:45:13
@ninjagecko是正确的 - 如果缺省值构造起来很昂贵,并且您关心性能,那么您将不想使用get/setdefault。在这种情况下,我经常使用'try:...除了KeyError:'成语,特别是如果我期望关键'未命中'是罕见的。 – Whatang 2011-05-31 00:11:19
@ninjagecko,Whatang:'value = mydict ['index']如果'index'在mydict else 1234'是懒惰的线索。我只想说清楚它在这里并不重要,因为1234创建起来非常便宜。 – 2011-05-31 01:16:11
或者使用setdefault()
- 像get()
,但它返回之前将钥匙:
value = mydict.setdefault('index', 1024)
需要注意的是,由于python是一种非惰性语言,因此将评估“默认值”表达式是否实际最终使用它。 (与不会评估它的'if'语句相反) – ninjagecko 2011-05-30 23:45:21
的get
和setdefault
方法是知道重要的是,他们应该在任何Python程序员的工具箱。
这样做的另一个重要方法是使用collections.defaultdict
,因为那样你就可以在一个地方定义你的“默认”,而不必在任何使用字典的地方将它分散到整个代码中,即不要重复你自己。然后,如果您更改默认值,则不需要通过代码来查找所有这些获取和setdefaults。例如
>>> 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
好的,这个例子有点做作,但我相信你可以想到更好的用途。假设你有一个昂贵的类来构建 - 只有当密钥不存在时才创建实例,与调用get
和setdefault
(例如,
>>> 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
。
另外值得注意的是,'setdefault()'和'defaultdict'都具有将任何缺少的键添加到字典的副作用。当使用'defaultdict'时,如果您希望默认值因键而异(因为工厂函数未通过查找键),您可能需要的不仅仅是一个简单的* default_factory *函数。 – martineau 2011-05-31 00:57:17
另外一件事情,'defaultdict'直到Python 2.5(并且OP使用2.4)才被添加。 – martineau 2011-05-31 01:11:17
'defaultdict'看起来很神奇,因为它是懒惰的,所以lambda不会被评估,除非需要;希望我可以upvote更 – ninjagecko 2011-05-31 01:46:19
collections
模块defaultdict
类可能会有所帮助。不幸的是,它直到Python 2.5才被引入,并且它并不是,而是你的代码所做的。这里有几个不同点:
False
值的值。如果这行你可以用这样的模仿精髓之一老年蟒蛇:
try:
from collections import defaultdict
except ImportError:
class defaultdict(dict):
def __init__(self, default_factory=None, *a, **kw):
dict.__init__(self, *a, **kw)
self.default_factory = default_factory
def __getitem__(self, key):
try:
return dict.__getitem__(self, key)
except KeyError:
return self.__missing__(key)
def __missing__(self, key):
self[key] = value = self.default_factory()
return value
一个更完整的仿真配方可在ActiveState。即使你有Python 2.5+,你也可能想要派生自己的类来定制,以获得你想要的确切行为。除了检查“假”真值并且可能不会在字典中添加任何缺少的值之外,还可以为它提供单独的与多个默认值对应的默认值的字典,而不是“一刀切”。有关的方法请参阅Is there a way to set multiple defaults on a Python dict using another dict?。
+1用于基本的回退实现。 – lambacck 2011-05-31 02:59:25
实际上,您的代码执行此操作:“从dict的值初始化,如果存在,*不认为是布尔值False *,否则使用默认值。 – martineau 2011-05-31 01:08:43
对!忘了说'索引'从来没有布尔(代码约束)对不起。 – Caruccio 2011-05-31 21:07:16
如果它们实际上是一个布尔类型就没关系,因为在Python中有很多东西,比如'None','()','[]','''','{}','0',如果在逻辑表达式中使用'0.0',则认为'False' - 有些人称其为“真实性”(http://en.wikipedia.org/wiki/Truthiness)。 – martineau 2011-06-01 00:32:28