什麼是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