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