Вопрос-Ответ

Collections.defaultdict difference with normal dict

Разница Collections.defaultdict с обычным dict

Я прочитал примеры в документах python, но все еще не могу понять, что означает этот метод. Кто-нибудь может помочь? Вот два примера из документов python

>>> from collections import defaultdict

>>> s = 'mississippi'
>>> d = defaultdict(int)
>>> for k in s:
... d[k] += 1
...
>>> d.items()
dict_items([('m', 1), ('i', 4), ('s', 4), ('p', 2)])

и

>>> s = [('yellow', 1), ('blue', 2), ('yellow', 3), ('blue', 4), ('red', 1)]
>>> d = defaultdict(list)
>>> for k, v in s:
... d[k].append(v)
...
>>> d.items()
[('blue', [2, 4]), ('red', [1]), ('yellow', [1, 3])]

параметры int и list предназначены для чего?

Переведено автоматически
Ответ 1

Обычно словарь Python выдает KeyError, если вы пытаетесь получить элемент с ключом, которого в данный момент нет в словаре. defaultdict В отличие от этого, просто создаст любые элементы, к которым вы попытаетесь получить доступ (при условии, конечно, что они еще не существуют). Чтобы создать такой элемент "по умолчанию", он вызывает объект function, который вы передаете конструктору (точнее, это произвольный "вызываемый" объект, который включает объекты function и type). В первом примере элементы по умолчанию создаются с помощью int(), который вернет целочисленный объект 0. Во втором примере элементы по умолчанию создаются с помощью list(), который возвращает новый пустой объект list .

Ответ 2

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

Например:

somedict = {}
print(somedict[3]) # KeyError

someddict = defaultdict(int)
print(someddict[3]) # print int(), thus 0
Ответ 3

defaultdict

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

как определено Дугом Хеллманном в Стандартной библиотеке Python на примере

Как использовать defaultdict

Импорт defaultdict

>>> from collections import defaultdict

Инициализировать defaultdict

Инициализируйте его, передав


вызывается в качестве первого аргумента (обязательно)


>>> d_int = defaultdict(int)
>>> d_list = defaultdict(list)
>>> def foo():
... return 'default value'
...
>>> d_foo = defaultdict(foo)
>>> d_int
defaultdict(<type 'int'>, {})
>>> d_list
defaultdict(<type 'list'>, {})
>>> d_foo
defaultdict(<function foo at 0x7f34a0a69578>, {})

** kwargs в качестве второго аргумента (необязательно)


>>> d_int = defaultdict(int, a=10, b=12, c=13)
>>> d_int
defaultdict(<type 'int'>, {'a': 10, 'c': 13, 'b': 12})

или

>>> kwargs = {'a':10,'b':12,'c':13}
>>> d_int = defaultdict(int, **kwargs)
>>> d_int
defaultdict(<type 'int'>, {'a': 10, 'c': 13, 'b': 12})

Как это работает

Поскольку это дочерний класс стандартного словаря, он может выполнять все те же функции.

Но в случае передачи неизвестного ключа он возвращает значение по умолчанию вместо ошибки. Например:

>>> d_int['a']
10
>>> d_int['d']
0
>>> d_int
defaultdict(<type 'int'>, {'a': 10, 'c': 13, 'b': 12, 'd': 0})

Если вы хотите изменить значение по умолчанию, перезапишите default_factory:

>>> d_int.default_factory = lambda: 1
>>> d_int['e']
1
>>> d_int
defaultdict(<function <lambda> at 0x7f34a0a91578>, {'a': 10, 'c': 13, 'b': 12, 'e': 1, 'd': 0})

или

>>> def foo():
... return 2
>>> d_int.default_factory = foo
>>> d_int['f']
2
>>> d_int
defaultdict(<function foo at 0x7f34a0a0a140>, {'a': 10, 'c': 13, 'b': 12, 'e': 1, 'd': 0, 'f': 2})

Примеры в вопросе

Пример 1

Поскольку int был передан как default_factory , любой неизвестный ключ по умолчанию вернет 0.

Теперь, когда строка передается в цикле, это увеличит количество этих алфавитов в d.

>>> s = 'mississippi'
>>> d = defaultdict(int)
>>> d.default_factory
<type 'int'>
>>> for k in s:
... d[k] += 1
>>> d.items()
[('i', 4), ('p', 2), ('s', 4), ('m', 1)]
>>> d
defaultdict(<type 'int'>, {'i': 4, 'p': 2, 's': 4, 'm': 1})

Пример 2

Поскольку список был передан как default_factory, любой неизвестный (несуществующий) ключ по умолчанию вернет [ ] (т.е.. список).

Теперь, когда список кортежей передается в цикле, он добавит значение в d[color]

>>> s = [('yellow', 1), ('blue', 2), ('yellow', 3), ('blue', 4), ('red', 1)]
>>> d = defaultdict(list)
>>> d.default_factory
<type 'list'>
>>> for k, v in s:
... d[k].append(v)
>>> d.items()
[('blue', [2, 4]), ('red', [1]), ('yellow', [1, 3])]
>>> d
defaultdict(<type 'list'>, {'blue': [2, 4], 'red': [1], 'yellow': [1, 3]})
Ответ 4

Словари - это удобный способ хранения данных для последующего извлечения по имени (ключу). Ключи должны быть уникальными, неизменяемыми объектами и обычно представляют собой строки. Значения в словаре могут быть любыми. Для многих приложений значениями являются простые типы, такие как целые числа и строки.

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

defaultdict никогда не вызовет KeyError . Любой несуществующий ключ получает значение, возвращаемое фабрикой по умолчанию.

from collections import defaultdict
ice_cream = defaultdict(lambda: 'Vanilla')

ice_cream['Sarah'] = 'Chunky Monkey'
ice_cream['Abdul'] = 'Butter Pecan'

print(ice_cream['Sarah'])
>>>Chunky Monkey

print(ice_cream['Joe'])
>>>Vanilla

Вот еще один пример того, как с помощью defaultdict мы можем снизить сложность

from collections import defaultdict
# Time complexity O(n^2)
def delete_nth_naive(array, n):
ans = []
for num in array:
if ans.count(num) < n:
ans.append(num)
return ans

# Time Complexity O(n), using hash tables.
def delete_nth(array,n):
result = []
counts = defaultdict(int)

for i in array:
if counts[i] < n:
result.append(i)
counts[i] += 1
return result


x = [1,2,3,1,2,1,2,3]
print(delete_nth(x, n=2))
print(delete_nth_naive(x, n=2))

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

2023-08-07 07:47 python dictionary