Инициализируйте переменную Python из возможного пропущенного значения dict

1

Каков питонический способ сделать это?

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

Инициализировать из значения dict, если оно присутствует, в противном случае использовать значение по умолчанию.

Получил некоторые ответы на LBYL и EAFP, но слишком подробный код: p

Я хочу, чтобы инициализировался какой-то one- line-.

Только PS: python- 2.4 (работает CentOS5)

  • 0
    Фактически ваш код делает это: «Инициализируйте из значения dict, если оно присутствует и не считается логическим значением False , в противном случае используйте значение по умолчанию».
  • 0
    Правильно! Забыл сказать, что 'index' никогда не бывает логическим (ограничение кода) Извините.
Показать ещё 1 комментарий
Теги:
dictionary
indexing
initialization

4 ответа

11
Лучший ответ
value = mydict.get('index', 1024)

(Обратите внимание, что это не совсем эквивалентно вашему коду, так как он будет использовать 1024, только если ключ index отсутствует, а ваш код также использует 1024, когда значение, соответствующее клавише index это ложь. Из вашего объяснения я полагаю, что первое - это то, что вы действительно хотите.)

  • 1
    Чрезвычайно важно отметить, что, поскольку python является языком без ленивости, выражение «значение по умолчанию» будет оцениваться независимо от того, используете ли вы его в действительности или нет. (В отличие от утверждения if которое не будет его оценивать.)
  • 0
    @ninjagecko прав - если значение по умолчанию является дорогостоящим для построения, и вы заботитесь о производительности, вам следует избегать использования get / setdefault . В этом случае я часто использую try: ... except KeyError: idiom, особенно если я ожидаю, что «пропущенные» ключи будут редкими.
Показать ещё 6 комментариев
2

В качестве альтернативы используйте setdefault() - как get(), но он вставляет ключ перед возвратом значения:

value = mydict.setdefault('index', 1024)
  • 1
    Чрезвычайно важно отметить, что, поскольку python является языком без ленивости, выражение «значение по умолчанию» будет оцениваться независимо от того, используете ли вы его в действительности или нет. (В отличие от утверждения if которое не будет его оценивать.)
1

Класс collections module defaultdict может оказаться полезным. К сожалению, он не был введен до Python 2.5, и он не делает точно, что делает ваш код. Вот несколько отличий:

  • Он получает только значение, когда отсутствует ключ, а не когда он есть, но имеет значение False.
  • Если отсутствует ключ looked- up, он добавит его в словарь со значением по умолчанию, а также вернет значение по умолчанию.
  • Все отсутствующие значения получают одинаковое значение по умолчанию.

Если это нормально, вы можете эмулировать сущность одного из старых 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?.

  • 0
    +1 для базовой резервной реализации.
1

Методы 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.

  • 0
    Также стоит отметить, что setdefault() и defaultdict имеют побочный эффект добавления отсутствующего ключа в словарь. Кроме того, при использовании defaultdict вам может потребоваться больше, чем простая функция default_factory, если вы хотите, чтобы значение по умолчанию изменялось в зависимости от ключа (потому что заводская функция не передала ключ, являющийся поиском).
  • 1
    Кроме того, defaultdict не был добавлен до Python 2.5 (а OP использует 2.4).
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню