Python defaultdict и лямбда

в чужом коде я прочитал следующие две строки:

x = defaultdict(lambda: 0)
y = defaultdict(lambda: defaultdict(lambda: 0))

поскольку аргумент defaultdict является фабрикой по умолчанию, я думаю,что первая строка означает, что когда я вызываю x[k] для несуществующего ключа k (например, оператор V=x[k]), пара ключ-значение (k, 0) будет автоматически добавлена в словарь, как если бы оператор x[k]=0 был сначала выполнен. Я прав?

и что? Кажется, что фабрика по умолчанию создаст defaultdict с default 0. Но что это значит конкретно? Я попытался поиграть с ним в оболочке Python, но не смог понять, что это такое.

5 ответов


я думаю, что первая строка означает, что, когда я называю x[k] для несуществующего ключа k (например, утверждение типа v=x[k]), пара ключ-значение (k,0) будет автоматически добавлен в словарь, как если бы оператор x[k]=0 сначала выполняется.

это верно. Это более идиоматично написано

x = defaultdict(int)

в случае y, когда вы делаете y["ham"]["spam"] ключ "ham" вставить в y если он не существует. Значение связанный с ним становится defaultdict, в котором "spam" автоматически вставляется со значением 0.

И. Е., y вид "двух-ярусная" defaultdict. Если "ham" not in y, затем оценки y["ham"]["spam"] - это

y["ham"] = {}
y["ham"]["spam"] = 0

в терминах обычных dict.


defaultdict принимает нулевой аргумент, вызываемый его конструктором, который вызывается, когда ключ не найден, как вы правильно объяснили.

lambda: 0, конечно, всегда будет возвращать ноль, но предпочтительным методом для этого является defaultdict(int), который будет делать то же самое.

что касается второй части, автор хотел создать новый defaultdict(int), или вложенный словарь, когда ключ не найден в словаре.


вы правы в том,что делает первый. Что касается y, он создаст defaultdict со значением по умолчанию 0, когда ключ не существует в y, поэтому вы можете думать об этом как о вложенном словаре. Рассмотрим следующий пример:

y = defaultdict(lambda: defaultdict(lambda: 0))
print y['k1']['k2']   # 0
print dict(y['k1'])   # {'k2': 0}

чтобы создать эквивалентную вложенную структуру словаря без defaultdict, вам нужно будет создать внутренний dict для y['k1'] и затем установить y['k1']['k2'] до 0, но defaultdict делает все это за кулисами, когда он сталкивается с ключами не видел:

y = {}
y['k1'] = {}
y['k1']['k2'] = 0

следующая функция может помочь для игры с этим на интерпретаторе, чтобы улучшить ваше понимание:

def to_dict(d):
    if isinstance(d, defaultdict):
        return dict((k, to_dict(v)) for k, v in d.items())
    return d

это вернет эквивалент dict вложенного defaultdict, который намного легче читать, например:

>>> y = defaultdict(lambda: defaultdict(lambda: 0))
>>> y['a']['b'] = 5
>>> y
defaultdict(<function <lambda> at 0xb7ea93e4>, {'a': defaultdict(<function <lambda> at 0xb7ea9374>, {'b': 5})})
>>> to_dict(y)
{'a': {'b': 5}}

y = defaultdict(lambda:defaultdict(lambda:0))

будет полезно, если вы попробовать этот y['a']['b'] += 1


все ответы достаточно хороши, пока я даю ответ, чтобы добавить больше информации:

" defaultdict требует аргумент, который вызывается. Возвращаемый результат вызываемого объекта-это значение по умолчанию, возвращаемое словарем при попытке доступа к словарю с несуществующим ключом."

вот пример

SAMPLE= {'Age':28, 'Salary':2000}
SAMPLE = defaultdict(lambda:0,SAMPLE)

>>> SAMPLE
defaultdict(<function <lambda> at 0x0000000002BF7C88>, {'Salary': 2000, 'Age': 28})

>>> SAMPLE['Age']----> This will return 28
>>> SAMPLE['Phone']----> This will return 0   # you got 0 as output for a non existing key inside SAMPLE