Инициализируйте переменную Python из возможного пропущенного значения dict - PullRequest
1 голос
/ 31 мая 2011

Что такое Pythonic способ сделать это?

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

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

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

Мне нужна инициализация в одну строку.

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

Ответы [ 4 ]

11 голосов
/ 31 мая 2011
value = mydict.get('index', 1024)

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

2 голосов
/ 31 мая 2011

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

value = mydict.setdefault('index', 1024)
1 голос
/ 31 мая 2011

Может помочь класс collections module 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+, вы можете захотеть получить свой собственный класс для настройки в соответствии с желаемым поведением. Помимо проверки «ложных» значений истинности и, возможно, отсутствия добавления недостающих в словарь, вы также можете предоставить ему отдельный словарь из нескольких значений по умолчанию, соответствующих разным ключам, вместо «один размер подходит всем». Чтобы узнать, как это сделать, см. Есть ли способ установить несколько значений по умолчанию для Python, используя другой dict? .

1 голос
/ 31 мая 2011

Важно знать методы 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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...