Python · Синтаксис · Начальный уровень

Методы словарей

10 задач

Освойте все основные методы словарей и dict comprehension для эффективной работы с данными.

Методы словарей

#
Словарь — это неупорядоченная коллекция пар ключ-значение. Ключи должны быть неизменяемыми (строки, числа, кортежи); значения — любого типа. Словари **мутабельны**: можно добавлять, обновлять и удалять записи. ## Безопасное чтение с get() ```python user = {"name": "Alice", "age": 30} print(user["name"]) # "Alice" print(user.get("email")) # None — без KeyError! print(user.get("email", "not set")) # "not set" ``` Всегда предпочитайте `get()` вместо `[]`, если ключ может отсутствовать. Прямой доступ через `[]` кидает `KeyError`, если ключ не существует. ## setdefault() ```python d = {} d.setdefault("count", 0) # устанавливает "count" = 0 только если его нет d["count"] += 1 print(d) # {"count": 1} # Классический паттерн подсчёта слов: text = "apple banana apple cherry apple" freq = {} for word in text.split(): freq.setdefault(word, 0) freq[word] += 1 print(freq) # {"apple": 3, "banana": 1, "cherry": 1} ``` ## update() ```python defaults = {"color": "blue", "size": 10, "shape": "circle"} overrides = {"color": "red", "weight": 5} defaults.update(overrides) print(defaults) # {"color": "red", "size": 10, "shape": "circle", "weight": 5} ``` `update()` модифицирует словарь на месте. Для слияния без мутации используйте `{**d1, **d2}` (Python 3.5+) или `d1 | d2` (Python 3.9+). ## pop() и popitem() ```python d = {"a": 1, "b": 2, "c": 3} val = d.pop("b") # удаляет ключ "b", возвращает 2 print(val, d) # 2 {"a": 1, "c": 3} val = d.pop("x", "default") # возвращает "default" — без KeyError print(val) # "default" key, val = d.popitem() # удаляет и возвращает последнюю вставленную (k, v) print(key, val) # "c" 3 ``` ## keys(), values(), items() ```python person = {"name": "Bob", "age": 25, "city": "Kyiv"} print(list(person.keys())) # ["name", "age", "city"] print(list(person.values())) # ["Bob", 25, "Kyiv"] print(list(person.items())) # [("name", "Bob"), ("age", 25), ("city", "Kyiv")] # Итерация по парам ключ-значение for key, value in person.items(): print(f"{key}: {value}") ``` ## copy() и clear() ```python original = {"a": 1, "b": 2} copy = original.copy() # поверхностная копия copy["c"] = 3 print(original) # {"a": 1, "b": 2} — не изменился original.clear() print(original) # {} ```

Dict Comprehension и вложенные словари

#
## Dict comprehension Dict comprehension создаёт новый словарь из любого итерируемого в одном читабельном выражении. ```python # Базовый: {ключ: значение for элемент in итерируемый} squares = {x: x**2 for x in range(1, 6)} print(squares) # {1: 1, 2: 4, 3: 9, 4: 16, 5: 25} # Из двух списков через zip keys = ["a", "b", "c"] values = [1, 2, 3] d = {k: v for k, v in zip(keys, values)} print(d) # {"a": 1, "b": 2, "c": 3} # С условием (фильтр) even_squares = {x: x**2 for x in range(10) if x % 2 == 0} print(even_squares) # {0: 0, 2: 4, 4: 16, 6: 36, 8: 64} # Трансформация существующего словаря prices = {"apple": 1.2, "banana": 0.5, "cherry": 3.0} discounted = {item: round(price * 0.9, 2) for item, price in prices.items()} print(discounted) # {"apple": 1.08, "banana": 0.45, "cherry": 2.7} ``` ## Инверсия словаря ```python original = {"a": 1, "b": 2, "c": 3} inverted = {v: k for k, v in original.items()} print(inverted) # {1: "a", 2: "b", 3: "c"} ``` Работает только если все значения уникальны и хешируемы. ## Вложенные словари ```python users = { "alice": {"age": 30, "role": "admin"}, "bob": {"age": 25, "role": "user"}, } # Доступ к вложенному значению print(users["alice"]["role"]) # "admin" # Безопасный доступ — цепочка get() role = users.get("charlie", {}).get("role", "guest") print(role) # "guest" — без KeyError даже если "charlie" не существует # Обновление вложенного значения users["alice"]["age"] = 31 ``` ## Группировка через словари ```python words = ["apple", "ant", "banana", "bear", "cherry"] by_letter = {} for word in words: letter = word[0] by_letter.setdefault(letter, []) by_letter[letter].append(word) print(by_letter) # {"a": ["apple", "ant"], "b": ["banana", "bear"], "c": ["cherry"]} ``` ## Слияние словарей (Python 3.9+) ```python d1 = {"a": 1, "b": 2} d2 = {"b": 3, "c": 4} merged = d1 | d2 # новый словарь, d2 побеждает при конфликтах print(merged) # {"a": 1, "b": 3, "c": 4} d1 |= d2 # обновляет d1 на месте print(d1) # {"a": 1, "b": 3, "c": 4} ```

Справочник: методы словарей

#
## Основные методы | Метод | Что делает | Возвращает | |---|---|---| | `d[key]` | Получить значение (KeyError если нет) | значение | | `d.get(key)` | Получить значение или `None` | значение или None | | `d.get(key, default)` | Получить значение или default | значение или default | | `d[key] = val` | Установить / обновить ключ | — | | `d.setdefault(key, default)` | Установить default только если ключа нет | значение | | `d.update(other)` | Слить `other` в `d` (на месте) | `None` | | `d.pop(key)` | Удалить и вернуть значение (KeyError если нет) | значение | | `d.pop(key, default)` | Удалить и вернуть значение или default | значение или default | | `d.popitem()` | Удалить и вернуть последнюю пару (key, value) | (key, value) | | `d.keys()` | Представление всех ключей | dict_keys | | `d.values()` | Представление всех значений | dict_values | | `d.items()` | Представление всех пар (key, value) | dict_items | | `d.copy()` | Поверхностная копия | новый dict | | `d.clear()` | Удалить все записи | `None` | | `key in d` | Проверить наличие ключа | bool | | `len(d)` | Количество пар ключ-значение | int | ## Синтаксис dict comprehension ```python {key_expr: val_expr for var in iterable} {key_expr: val_expr for var in iterable if condition} {key_expr: val_expr for k, v in d.items()} ``` ## Слияние словарей ```python # Python 3.5+: распаковка merged = {**d1, **d2} # Python 3.9+: оператор | merged = d1 | d2 d1 |= d2 # на месте # Все версии: update d1.update(d2) ``` ## Безопасный доступ к вложенным данным ```python # Цепочка .get() чтобы избежать KeyError на любом уровне value = data.get("user", {}).get("address", {}).get("city", "unknown") ``` ## Распространённые паттерны ```python # Частота слов freq = {} for word in text.split(): freq[word] = freq.get(word, 0) + 1 # Группировка по категории groups = {} for item in items: groups.setdefault(item.category, []).append(item) # Инвертирование inv = {v: k for k, v in d.items()} # Фильтрация по значению filtered = {k: v for k, v in d.items() if v > 0} ```
01

Безопасное чтение конфига

#

Напишите функцию `get_setting(config, key, default=None)`, которая безопасно читает значение из конфигурационного словаря. Если ключ есть — возвращает значение, иначе — `default`. Пример: `get_setting({"debug": True}, "debug")` → `True`, `get_setting({"debug": True}, "port", 8080)` → `8080`.

def get_setting(config, key, default=None):
    pass


print(get_setting({"debug": True}, "debug"))          # True
print(get_setting({"debug": True}, "port", 8080))     # 8080
print(get_setting({"debug": True}, "host"))           # None
Решение
def get_setting(config, key, default=None):
    return config.get(key, default)


print(get_setting({"debug": True}, "debug"))          # True
print(get_setting({"debug": True}, "port", 8080))     # 8080
print(get_setting({"debug": True}, "host"))           # None
02

Частота слов

#

Напишите функцию `word_freq(text)`, которая возвращает словарь, где каждое слово соответствует количеству его вхождений. Слова переводятся в нижний регистр (для простоты считайте, что слова разделены только пробелами). Пример: `word_freq("the cat sat the cat")` → `{"the": 2, "cat": 2, "sat": 1}`.

def word_freq(text):
    pass


print(word_freq("the cat sat the cat"))
# {"the": 2, "cat": 2, "sat": 1}
Решение
def word_freq(text):
    counts = {}
    for word in text.lower().split():
        counts[word] = counts.get(word, 0) + 1
    return counts


print(word_freq("the cat sat the cat"))
# {"the": 2, "cat": 2, "sat": 1}
03

Слияние с переопределением

#

Напишите функцию `merge(base, overrides)`, которая возвращает новый словарь со всеми ключами из `base`, но если ключ есть в `overrides` — берётся значение из `overrides`. Исходные словари не должны изменяться. Пример: `merge({"a": 1, "b": 2}, {"b": 99, "c": 3})` → `{"a": 1, "b": 99, "c": 3}`.

def merge(base, overrides):
    pass


print(merge({"a": 1, "b": 2}, {"b": 99, "c": 3}))
# {"a": 1, "b": 99, "c": 3}
Решение
def merge(base, overrides):
    return {**base, **overrides}


print(merge({"a": 1, "b": 2}, {"b": 99, "c": 3}))
# {"a": 1, "b": 99, "c": 3}
04

Безопасное удаление ключа

#

Напишите функцию `remove_key(d, key)`, которая удаляет `key` из словаря `d` если он существует, и возвращает удалённое значение. Если ключ не существует — возвращает `None` без ошибки. Функция должна изменять `d` на месте. Пример: `d = {"a": 1, "b": 2}; remove_key(d, "a")` → возвращает `1`, `d` становится `{"b": 2}`.

def remove_key(d, key):
    pass


d = {"a": 1, "b": 2}
print(remove_key(d, "a"))   # 1
print(d)                    # {"b": 2}
print(remove_key(d, "x"))   # None
Решение
def remove_key(d, key):
    return d.pop(key, None)


d = {"a": 1, "b": 2}
print(remove_key(d, "a"))   # 1
print(d)                    # {"b": 2}
print(remove_key(d, "x"))   # None
05

Словарь квадратов

#

Напишите функцию `squares_dict(n)` с использованием dict comprehension, которая возвращает словарь, где ключи — целые числа от 1 до `n`, а значения — их квадраты. Пример: `squares_dict(5)` → `{1: 1, 2: 4, 3: 9, 4: 16, 5: 25}`.

def squares_dict(n):
    pass


print(squares_dict(5))
# {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
Решение
def squares_dict(n):
    return {i: i ** 2 for i in range(1, n + 1)}


print(squares_dict(5))
# {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
06

Фильтрация по значению

#

Напишите функцию `filter_dict(d, min_value)`, которая возвращает новый словарь, содержащий только пары ключ-значение, где значение больше или равно `min_value`. Пример: `filter_dict({"a": 5, "b": 1, "c": 8, "d": 3}, 4)` → `{"a": 5, "c": 8}`.

def filter_dict(d, min_value):
    pass


print(filter_dict({"a": 5, "b": 1, "c": 8, "d": 3}, 4))
# {"a": 5, "c": 8}
Решение
def filter_dict(d, min_value):
    return {k: v for k, v in d.items() if v >= min_value}


print(filter_dict({"a": 5, "b": 1, "c": 8, "d": 3}, 4))
# {"a": 5, "c": 8}
07

Инвертирование словаря

#

Напишите функцию `invert(d)`, которая меняет местами ключи и значения словаря и возвращает новый инвертированный словарь. Считайте, что все значения уникальны и хешируемы. Пример: `invert({"a": 1, "b": 2, "c": 3})` → `{1: "a", 2: "b", 3: "c"}`.

def invert(d):
    pass


print(invert({"a": 1, "b": 2, "c": 3}))
# {1: "a", 2: "b", 3: "c"}
Решение
def invert(d):
    return {v: k for k, v in d.items()}


print(invert({"a": 1, "b": 2, "c": 3}))
# {1: "a", 2: "b", 3: "c"}
08

Группировка по первой букве

#

Напишите функцию `group_by_letter(words)`, которая возвращает словарь, где каждый ключ — это буква, а значение — отсортированный список слов, начинающихся с этой буквы. Пример: `group_by_letter(["apple", "ant", "banana", "bear"])` → `{"a": ["ant", "apple"], "b": ["banana", "bear"]}`.

def group_by_letter(words):
    pass


print(group_by_letter(["apple", "ant", "banana", "bear"]))
# {"a": ["ant", "apple"], "b": ["banana", "bear"]}
Решение
def group_by_letter(words):
    result = {}
    for word in words:
        key = word[0]
        result.setdefault(key, []).append(word)
    for key in result:
        result[key].sort()
    return result


print(group_by_letter(["apple", "ant", "banana", "bear"]))
# {"a": ["ant", "apple"], "b": ["banana", "bear"]}
09

Безопасный доступ к вложенным данным

#

Напишите функцию `deep_get(data, *keys)`, которая безопасно получает значения из вложенных словарей по цепочке ключей. Возвращает `None` если любой ключ отсутствует. Пример: `deep_get({"user": {"address": {"city": "Kyiv"}}}, "user", "address", "city")` → `"Kyiv"`, `deep_get({"user": {}}, "user", "address", "city")` → `None`.

def deep_get(data, *keys):
    pass


user = {"user": {"address": {"city": "Kyiv"}}}
print(deep_get(user, "user", "address", "city"))   # Kyiv
print(deep_get(user, "user", "phone"))              # None
Решение
def deep_get(data, *keys):
    for key in keys:
        if not isinstance(data, dict):
            return None
        data = data.get(key)
    return data


user = {"user": {"address": {"city": "Kyiv"}}}
print(deep_get(user, "user", "address", "city"))   # Kyiv
print(deep_get(user, "user", "phone"))              # None
10

Словарь из двух списков

#

Напишите функцию `zip_to_dict(keys, values)`, которая создаёт словарь из двух списков одинаковой длины. Если длины разные — кидает `ValueError` с сообщением `"Lists must have the same length"`. Пример: `zip_to_dict(["a", "b", "c"], [1, 2, 3])` → `{"a": 1, "b": 2, "c": 3}`.

def zip_to_dict(keys, values):
    pass


print(zip_to_dict(["a", "b", "c"], [1, 2, 3]))
# {"a": 1, "b": 2, "c": 3}
zip_to_dict(["x", "y"], [1, 2, 3])  # raises ValueError
Решение
def zip_to_dict(keys, values):
    if len(keys) != len(values):
        raise ValueError("Lists must have the same length")
    return dict(zip(keys, values))


print(zip_to_dict(["a", "b", "c"], [1, 2, 3]))
# {"a": 1, "b": 2, "c": 3}
try:
    zip_to_dict(["x", "y"], [1, 2, 3])
except ValueError as e:
    print(e)