Есть ли способ установить несколько значений по умолчанию для Python dict, используя другой dict? - PullRequest
8 голосов
/ 12 мая 2009

Предположим, у меня есть два слова в Python:

mydict = { 'a': 0 }

defaults = {
    'a': 5,
    'b': 10,
    'c': 15
}

Я хочу иметь возможность расширять mydict, используя значения по умолчанию от defaults, так что «a» остается тем же, а «b» и «c» заполнены. Я знаю о dict.setdefault() и dict.update(), но каждый из них выполняет только половину того, что я хочу - с dict.setdefault() я должен циклически перебирать каждую переменную в defaults; но с dict.update(), defaults сместит любые ранее существующие значения в mydict.

Есть ли какая-то функциональность, которую я не нахожу встроенной в Python, которая может сделать это? А если нет, то есть ли более Pythonic способ написания цикла для многократного вызова dict.setdefaults(), чем этот:

for key in defaults.keys():
    mydict.setdefault(key, defaults[key])

Контекст: я записываю некоторые данные в Python, которые контролируют, как анализировать дерево XML. Для каждого узла есть требование (то есть, как обрабатывать каждый узел), и я бы предпочел, чтобы данные, которые я записываю, были редкими, но заполненными значениями по умолчанию. Пример кода является просто примером ... реальный код имеет гораздо больше пар ключ / значение в стандартном dict.

(Я понимаю, что весь этот вопрос - всего лишь незначительная болтовня, но это беспокоит меня, поэтому мне было интересно, есть ли лучший способ сделать это, о котором я не знаю.)

Ответы [ 5 ]

9 голосов
/ 12 мая 2009

Не могли бы вы сделать mydict копией по умолчанию? Таким образом, mydict будет иметь все правильные значения для начала?

mydict = default.copy()
5 голосов
/ 12 мая 2009

Вы можете сделать это так же, как коллекции Python. DefaultDict работает:

class MultiDefaultDict(dict):
    def __init__(self, defaults, **kwargs):
        self.defaults = defaults
        self.update(kwargs)
    def __missing__(self, key):
        return self.defaults[key]

>>> mydict2 = MultiDefaultDict(defaults, a=0)
>>> mydict2['a']
0
>>> mydict2['b']
10
>>> mydict2
{'a': 0}

Другие опубликованные решения дублируют все значения по умолчанию; этот делится ими, как и просил. Вы можете или не хотите переопределять другие методы dict, такие как __contains __ (), __iter __ (), items (), keys (), values ​​() - этот класс, как определено здесь, выполняет итерации только для элементов не по умолчанию.

4 голосов
/ 12 мая 2009

Если вы не против создать новый словарь в процессе, это поможет:

newdict = dict(defaults)
newdict.update(mydict)

Теперь newdict содержит то, что вам нужно.

0 голосов
/ 12 мая 2009

Лично мне нравится добавлять объект словаря. Он работает в основном как словарь, за исключением того, что сначала нужно создать объект.

class d_dict(dict):
    'Dictionary object with easy defaults.'
    def __init__(self,defaults={}):
        self.setdefault(defaults)           
    def setdefault(self,defaults):
        for key, value in defaults.iteritems():
            if not key in self:
                dict.__setitem__(self,key,value)

Это обеспечивает ту же функциональность, что и тип dict, за исключением того, что оно переопределяет метод setdefault () и принимает словарь, содержащий один или несколько элементов. Вы можете установить значения по умолчанию при создании.

Это всего лишь личное предпочтение. Как я понимаю, все, что делает dict.setdefault (), это устанавливает элементы, которые еще не были установлены. Так что, вероятно, самый простой вариант на месте:

new_dict = default_dict.copy()
new_dict.update({'a':0})

Однако, если вы делаете это более одного раза, вы можете сделать из этого функцию. На этом этапе может быть проще использовать пользовательский объект dict, чем постоянно добавлять значения по умолчанию в свои словари.

0 голосов
/ 12 мая 2009
defaults.update(mydict)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...