Пропустить до содержимого

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

[

Использование типа Python defaultdict для работы с отсутствующими ключами

Python defaultdict

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

Обработка отсутствующих ключей в словарях

Проблема отсутствующих ключей в словарях возникает, когда вы пытаетесь получить доступ к несуществующему ключу или изменить его значение. В таком случае возникает ошибка KeyError, которая может прервать выполнение кода.

Стандартная библиотека Python предоставляет тип данных defaultdict, который позволяет обрабатывать отсутствующие ключи в словарях. Вместо возникновения ошибки, defaultdict автоматически создает отсутствующий ключ и назначает ему значение по умолчанию. Это очень полезный механизм для обработки отсутствующих ключей в словарях.

Понимание типа данных Python defaultdict

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

Использование типа данных Python defaultdict

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

Группировка элементов

from collections import defaultdict
data = [("apple", 1), ("banana", 2), ("orange", 3), ("apple", 4), ("banana", 5)]
grouped = defaultdict(list)
for key, value in data:
grouped[key].append(value)
print(grouped)

В этом примере список data содержит пары ключ-значение. Мы используем defaultdict с параметром list в качестве значения по умолчанию. Затем проходим по каждой паре ключ-значение и добавляем значение в соответствующий список в группированном словаре. Результат будет следующим:

defaultdict(<class 'list'>, {'apple': [1, 4], 'banana': [2, 5], 'orange': [3]})

Группировка уникальных элементов

from collections import defaultdict
data = ["apple", "banana", "orange", "apple", "banana"]
grouped = defaultdict(set)
for item in data:
grouped[item].add(item)
print(grouped)

В этом примере список data содержит элементы. Мы используем defaultdict с параметром set в качестве значения по умолчанию. Затем проходим по каждому элементу и добавляем его в соответствующее множество в группированном словаре. Таким образом, мы получим словарь, в котором ключами являются уникальные элементы, а значениями - множества, содержащие эти элементы. Результат будет следующим:

defaultdict(<class 'set'>, {'apple': {'apple'}, 'banana': {'banana'}, 'orange': {'orange'}})

Подсчет элементов

from collections import defaultdict
data = ["apple", "banana", "orange", "apple", "banana"]
counter = defaultdict(int)
for item in data:
counter[item] += 1
print(counter)

В этом примере список data содержит элементы. Мы используем defaultdict с параметром int в качестве значения по умолчанию. Затем проходим по каждому элементу и увеличиваем счетчик соответствующего элемента на 1. Результат будет следующим:

defaultdict(<class 'int'>, {'apple': 2, 'banana': 2, 'orange': 1})

Накопление значений

from collections import defaultdict
data = [("apple", 1), ("banana", 2), ("orange", 3), ("apple", 4), ("banana", 5)]
accumulator = defaultdict(int)
for key, value in data:
accumulator[key] += value
print(accumulator)

В этом примере список data содержит пары ключ-значение. Мы используем defaultdict с параметром int в качестве значения по умолчанию. Затем проходим по каждой паре ключ-значение и добавляем значение к накопителю соответствующего ключа. Результат будет следующим:

defaultdict(<class 'int'>, {'apple': 5, 'banana': 7, 'orange': 3})

Глубже в типе данных defaultdict

Рассмотрим некоторые другие важные аспекты типа данных defaultdict:

defaultdict против dict

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

from collections import defaultdict
d = defaultdict(int)
d["key"] = 1
print(d["key"]) # 1
print(d["unknown"]) # 0

В этом примере мы создаем defaultdict с параметром int в качестве значения по умолчанию. Затем мы добавляем значение 1 для ключа "key" и пытаемся получить значение для неизвестного ключа "unknown". Результат будет следующим:

1
0

Параметр default_factory

defaultdict принимает один обязательный аргумент при инициализации - функцию, которая будет вызываться для создания значения по умолчанию при отсутствующем ключе. Эта функция называется default_factory.

from collections import defaultdict
def default_value():
return "default"
d = defaultdict(default_value)
d["unknown"] = 1
print(d["unknown"]) # 1
print(d["missing"]) # "default"

В этом примере мы создаем функцию default_value, которая возвращает значение "default". Затем мы создаем defaultdict с этой функцией в качестве значения default_factory. Мы добавляем значение 1 для ключа "unknown" и пытаемся получить значение для отсутствующего ключа "missing". Результат будет следующим:

1
"default"

defaultdict против метода dict.setdefault()

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

from collections import defaultdict
d = defaultdict(int)
d["key"] = 1
print(d.setdefault("key", 2)) # 1
print(d.setdefault("unknown", 2)) # 2

В этом примере мы создаем defaultdict с параметром int в качестве значения по умолчанию. Затем мы добавляем значение 1 для ключа "key" и используем метод setdefault() для получения значения для ключа "key" и "unknown". Результат будет следующим:

1
2

Метод defaultdict.__missing__()

defaultdict также предоставляет метод __missing__(), который позволяет определить собственную логику для обработки отсутствующих ключей.

from collections import defaultdict
class CustomDefaultDict(defaultdict):
def __missing__(self, key):
return f"missing key: {key}"
d = CustomDefaultDict(int)
d["key"] = 1
print(d["key"]) # 1
print(d["unknown"]) # "missing key: unknown"

В этом примере мы создаем собственный класс CustomDefaultDict, который является подклассом defaultdict. Мы определяем метод __missing__(), который возвращает строку с информацией об отсутствующем ключе. Затем мы создаем экземпляр CustomDefaultDict с параметром int в качестве значения по умолчанию. Мы добавляем значение 1 для ключа "key" и пытаемся получить значение для неизвестного ключа "unknown". Результат будет следующим:

1
"missing key: unknown"

Эмуляция типа данных defaultdict

Если у вас нет доступа к модулю collections и типу данных defaultdict, вы можете эмулировать его функциональность с помощью обычного словаря и условной конструкции.

d = {}
key = "unknown"
if key not in d:
d[key] = "default"
print(d[key]) # "default"

В этом примере мы создаем обычный словарь d и проверяем, содержит ли он ключ "unknown". Если ключ отсутствует в словаре, мы добавляем его и присваиваем ему значение "default". Затем мы выводим значение для ключа "unknown". Результат будет следующим:

"default"

Передача аргументов в .default_factory

Функция default_factory может принимать аргументы, которые будут использоваться при создании значения по умолчанию. Есть несколько способов передать аргументы в default_factory:

Использование lambda-функции

from collections import defaultdict
d = defaultdict(lambda: "default")
d["unknown"] = 1
print(d["unknown"]) # 1
print(d["missing"]) # "default"

В этом примере мы используем lambda-функцию в качестве значения default_factory. В этой lambda-функции мы возвращаем значение "default". Мы добавляем значение 1 для ключа "unknown" и пытаемся получить значение для отсутствующего ключа "missing". Результат будет следующим:

1
"default"

Использование functools.partial()

from collections import defaultdict
from functools import partial
def default_value(arg):
return f"default {arg}"
d = defaultdict(partial(default_value, arg="argument"))
d["unknown"] = 1
print(d["unknown"]) # 1
print(d["missing"]) # "default argument"

В этом примере мы создаем функцию default_value, которая принимает аргумент arg и возвращает строку, содержащую значение этого аргумента. Затем мы используем функцию functools.partial() для задания значения default_factory для defaultdict. Мы добавляем значение 1 для ключа "unknown" и пытаемся получить значение для отсутствующего ключа "missing". Результат будет следующим:

1
"default argument"

Заключение

В этом руководстве вы узнали, как использовать тип данных defaultdict в Python для обработки отсутствующих ключей в словарях. Мы рассмотрели различные операции, которые можно выполнить с помощью defaultdict, такие как группировка, подсчет и накопление значений. Вы также узнали о некоторых важных аспектах defaultdict, таких как использование defaultdict против обычного словаря, параметр default_factory, метод __missing__, а также эмуляция defaultdict с помощью обычных словарей. Надеюсь, эти знания помогут вам эффективно использовать тип данных defaultdict в ваших программных задачах.