Каков питонический способ сделать это?
value = (mydict.has_key('index') and mydict['index']) or 1024
Инициализировать из значения dict, если оно присутствует, в противном случае использовать значение по умолчанию.
Получил некоторые ответы на LBYL и EAFP, но слишком подробный код: p
Я хочу, чтобы инициализировался какой-то one- line-.
Только PS: python- 2.4 (работает CentOS5)
value = mydict.get('index', 1024)
(Обратите внимание, что это не совсем эквивалентно вашему коду, так как он будет использовать 1024
, только если ключ index
отсутствует, а ваш код также использует 1024
, когда значение, соответствующее клавише index
это ложь. Из вашего объяснения я полагаю, что первое - это то, что вы действительно хотите.)
if
которое не будет его оценивать.)
get
/ setdefault
. В этом случае я часто использую try: ... except KeyError:
idiom, особенно если я ожидаю, что «пропущенные» ключи будут редкими.
В качестве альтернативы используйте setdefault()
- как get()
, но он вставляет ключ перед возвратом значения:
value = mydict.setdefault('index', 1024)
if
которое не будет его оценивать.)
Класс collections
module defaultdict
может оказаться полезным. К сожалению, он не был введен до Python 2.5, и он не делает точно, что делает ваш код. Вот несколько отличий:
False
.Если это нормально, вы можете эмулировать сущность одного из старых Pythons с чем-то вроде этого:
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+, вы можете захотеть получить свой собственный класс для настройки, чтобы иметь точное поведение, которое вы хотели. Помимо проверки значений истинности "False" и, возможно, не добавления каких-либо недостающих слов в словарь, вы также можете предоставить ему отдельный словарь с несколькими значениями по умолчанию, соответствующие разным клавишам, а не "один размер подходит всем". Для способов сделать это см. Есть ли способ установить несколько значений по умолчанию для Python-dict, используя другой dict?.
Методы get
и setdefault
важны для понимания, они должны быть в любой панели инструментов программиста Python.
Еще один важный способ сделать это - использовать collections.defaultdict
, потому что тогда вы можете определить свой "по умолчанию" в одном месте без необходимости разбросать его по всему вашему коду везде, где используется словарь, т.е. не повторяться. Затем, если вы измените значение по умолчанию, вам не нужно будет искать ваш код, находя все эти get и 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, если вы хотите, чтобы значение по умолчанию изменялось в зависимости от ключа (потому что заводская функция не передала ключ, являющийся поиском).
defaultdict
не был добавлен до Python 2.5 (а OP использует 2.4).