Словари Python: мощный инструмент для эффективного хранения данных

Пройдите тест, узнайте какой профессии подходите
Сколько вам лет
0%
До 18
От 18 до 24
От 25 до 34
От 35 до 44
От 45 до 49
От 50 до 54
Больше 55

Для кого эта статья:

  • Начинающие и средние разработчики Python, желающие улучшить свои навыки работы со словарями
  • Студенты и слушатели курсов по программированию, стремящиеся к практическому освоению Python
  • Опытные разработчики, интересующиеся продвинутыми техниками оптимизации и решениями с использованием словарей

    Словари в Python — настоящая швейцарская армейская бритва для хранения и манипулирования данными. От простого маппинга ключ-значение до сложных вложенных структур, словари предоставляют гибкую основу для решения широкого спектра задач программирования. Изучение этой структуры данных открывает путь к созданию более элегантного, эффективного и производительного кода, что отличает профессионала от начинающего программиста. 🚀 Погрузимся в мир Python-словарей, от фундаментальных основ до техник, которыми владеют только опытные разработчики.

Хотите быстро освоить словари Python и другие мощные инструменты этого языка? Курс Обучение Python-разработке от Skypro построен по принципу "практика с первого дня". Вы будете писать реальный код уже на первом занятии, работая над проектами под руководством экспертов-практиков. За 9 месяцев вы пройдете путь от новичка до junior-разработчика, способного создавать полноценные веб-приложения. И да, мы гарантируем трудоустройство!

Словари в Python: основы и преимущества структуры данных

Словари в Python представляют собой универсальные контейнеры данных, построенные на принципе ключ-значение. Эта структура данных имеет фундаментальное значение в языке и предоставляет оптимизированные методы доступа к данным с почти постоянным временем извлечения. Именно словари превращают Python в мощный инструмент для обработки информации. 🔍

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

Преимущества работы со словарями в Python:

  • Скорость доступа: O(1) для поиска, вставки и удаления — практически мгновенный доступ к данным
  • Гибкость: ключи и значения могут быть разных типов в одном словаре
  • Изменяемость: можно добавлять, изменять и удалять пары ключ-значение в любой момент
  • Встроенные методы: богатый набор встроенных методов для удобной работы со структурой
  • Выразительность: словарные литералы делают код более читаемым и лаконичным

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

Для сравнения, рассмотрим эффективность поиска данных в различных структурах:

Структура данных Время поиска (в среднем) Память Использование в задачах
Словари O(1) Высокая Кэширование, индексирование, подсчет
Списки O(n) Средняя Последовательные данные, итерации
Множества O(1) Высокая Уникальность элементов, пересечения
Кортежи O(n) Низкая Неизменяемые последовательности

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

Антон Смирнов, Senior Python Developer Помню свой первый крупный проект на Python — парсер новостных сайтов для аналитической компании. Мы обрабатывали тысячи статей ежедневно, извлекая ключевые слова и темы. Изначально я хранил все данные в массивах списков, и код превратился в запутанный лабиринт индексов и циклов. Переломный момент наступил, когда я переписал всю структуру хранения на словари. Вместо article_titles[i] и article_bodies[i] появился элегантный словарь article = {'title': '...', 'body': '...', 'keywords': [...]}. Производительность выросла на 40%, а объем кода сократился вдвое. Клиент был в восторге от скорости обработки, а я навсегда влюбился в словари Python.

Пошаговый план для смены профессии

Создание и базовые операции работы со словарями в Python

Создание словарей в Python может осуществляться несколькими способами, каждый из которых имеет свои преимущества в зависимости от контекста использования. Рассмотрим основные методы инициализации и наиболее часто используемые операции. 🛠️

Существует несколько способов создания словаря:

  • Используя литералы (фигурные скобки): user = {'name': 'John', 'age': 30}
  • Через конструктор dict(): user = dict(name='John', age=30)
  • Из списка кортежей: user = dict([('name', 'John'), ('age', 30)])
  • Генератором словарей: squares = {x: x*x for x in range(6)}
  • Создание пустого словаря: empty = {} или empty = dict()

Базовые операции со словарями:

Доступ к значениям

Python
Скопировать код
# Прямой доступ по ключу
user = {'name': 'John', 'age': 30}
print(user['name']) # John

# Безопасный доступ через get() с значением по умолчанию
print(user.get('email', 'not specified')) # not specified

Добавление и изменение элементов

Python
Скопировать код
# Добавление нового элемента
user['email'] = 'john@example.com'

# Изменение существующего элемента
user['age'] = 31

# Обновление нескольких элементов одновременно
user.update({'age': 32, 'city': 'New York'})

Удаление элементов

Python
Скопировать код
# Удаление по ключу с возвратом значения
age = user.pop('age') # age = 32, элемент удален из словаря

# Удаление и возврат произвольной пары
item = user.popitem() # Возвращает и удаляет последнюю добавленную пару

# Удаление по ключу без возврата значения
del user['email']

# Очистка всего словаря
user.clear()

Проверка наличия ключей

Python
Скопировать код
# Проверка наличия ключа
if 'name' in user:
print("Name exists")

# Проверка отсутствия ключа
if 'phone' not in user:
user['phone'] = '+1234567890'

Итерация по словарю

Python
Скопировать код
# Итерация по ключам (по умолчанию)
for key in user:
print(key)

# Явная итерация по ключам
for key in user.keys():
print(key)

# Итерация по значениям
for value in user.values():
print(value)

# Итерация по парам ключ-значение
for key, value in user.items():
print(f"{key}: {value}")

При работе со словарями важно помнить следующие особенности:

  • Ключи должны быть неизменяемыми (хешируемыми) типами. Например, нельзя использовать список как ключ
  • Значения могут быть любого типа, включая другие словари (вложенные структуры)
  • Порядок элементов в словарях гарантирован с Python 3.7 (элементы хранятся в порядке вставки)
  • Обращение к несуществующему ключу через квадратные скобки вызывает исключение KeyError

Вот таблица сравнения эффективности различных операций со словарями:

Операция Синтаксис Особенности Временная сложность
Доступ по ключу dict[key] Выбрасывает KeyError при отсутствии ключа O(1)
Метод get() dict.get(key, default) Безопасно возвращает default при отсутствии ключа O(1)
Добавление/изменение dict[key] = value Создает новую пару или обновляет существующую O(1)
Метод update() dict.update(other_dict) Обновляет несколько значений за один вызов O(len(other_dict))
Удаление ключа del dict[key] Выбрасывает KeyError при отсутствии ключа O(1)
Метод pop() dict.pop(key, default) Удаляет и возвращает значение O(1)
Итерация items() dict.items() Возвращает пары ключ-значение O(n)

Продвинутые техники и методы работы со словарями

Освоив базовые операции, перейдем к продвинутым техникам работы со словарями в Python, которые значительно расширят ваш арсенал инструментов и позволят писать более лаконичный и эффективный код. 🧠

Словарные включения (Dictionary Comprehensions)

Словарные включения — это элегантный способ создания словарей в одну строку, аналогичный списочным включениям:

Python
Скопировать код
# Создание словаря квадратов чисел
squares = {x: x**2 for x in range(10)}

# Фильтрация с условием
even_squares = {x: x**2 for x in range(10) if x % 2 == 0}

# Преобразование существующего словаря
prices = {'apple': 0.5, 'orange': 0.8, 'pear': 0.4}
discount_prices = {fruit: price * 0.9 for fruit, price in prices.items()}

# Создание словаря из двух списков
keys = ['a', 'b', 'c']
values = [1, 2, 3]
mapped = {k: v for k, v in zip(keys, values)}

Вложенные словари и глубокое копирование

Вложенные словари позволяют создавать сложные иерархические структуры данных:

Python
Скопировать код
# Вложенные словари
employee = {
'name': 'Anna',
'position': 'Developer',
'skills': {
'languages': ['Python', 'JavaScript'],
'frameworks': {
'backend': ['Django', 'Flask'],
'frontend': ['React']
}
}
}

# Доступ к вложенным элементам
backend_skills = employee['skills']['frameworks']['backend'] # ['Django', 'Flask']

# Глубокое копирование вложенных структур
import copy
employee_copy = copy.deepcopy(employee)

DefaultDict для автоматического создания значений

Класс defaultdict из модуля collections автоматически создает значения для несуществующих ключей:

Python
Скопировать код
from collections import defaultdict

# Словарь, автоматически создающий списки
word_counts = defaultdict(int)
for word in "how much wood would a woodchuck chuck".split():
word_counts[word] += 1
print(dict(word_counts)) # {'how': 1, 'much': 1, 'wood': 1, 'would': 1, 'a': 1, 'woodchuck': 1, 'chuck': 1}

# Создание вложенных структур с defaultdict
nested = defaultdict(lambda: defaultdict(list))
nested['users']['active'].append('user1')
nested['users']['active'].append('user2')

OrderedDict и сохранение порядка элементов

С Python 3.7+ обычные словари сохраняют порядок вставки, но OrderedDict предлагает дополнительные возможности:

Python
Скопировать код
from collections import OrderedDict

# Создание упорядоченного словаря
od = OrderedDict([('first', 1), ('second', 2), ('third', 3)])

# Перемещение элемента в конец
od.move_to_end('first')
print(od) # OrderedDict([('second', 2), ('third', 3), ('first', 1)])

# Обратный порядок
od = OrderedDict(sorted(od.items(), reverse=True))

Объединение и слияние словарей

Существует несколько способов объединения словарей:

Python
Скопировать код
# Python 3.9+ синтаксис объединения
dict1 = {'a': 1, 'b': 2}
dict2 = {'b': 3, 'c': 4}
merged = dict1 | dict2 # {'a': 1, 'b': 3, 'c': 4}

# Для более ранних версий Python
merged = {**dict1, **dict2}

# С помощью update (изменяет первый словарь)
result = dict1.copy()
result.update(dict2)

ChainMap для логического объединения нескольких словарей

ChainMap создает представление нескольких словарей как единого целого без их физического слияния:

Python
Скопировать код
from collections import ChainMap

# Несколько источников конфигурации
defaults = {'theme': 'dark', 'language': 'en'}
user_settings = {'theme': 'light'}

# Создание цепи с приоритетом: сначала проверяются user_settings, затем defaults
settings = ChainMap(user_settings, defaults)
print(settings['theme']) # 'light' из user_settings
print(settings['language']) # 'en' из defaults

Counter для подсчета элементов

Counter — специализированный словарь для подсчета объектов:

Python
Скопировать код
from collections import Counter

# Подсчет слов в тексте
words = "to be or not to be that is the question".split()
word_count = Counter(words)
print(word_count) # Counter({'to': 2, 'be': 2, 'or': 1, 'not': 1, 'that': 1, 'is': 1, 'the': 1, 'question': 1})

# Нахождение наиболее часто встречающихся элементов
most_common = word_count.most_common(2) # [('to', 2), ('be', 2)]

# Математические операции с счетчиками
counter1 = Counter(['a', 'b', 'c', 'a'])
counter2 = Counter(['a', 'd', 'e'])
print(counter1 + counter2) # Counter({'a': 3, 'b': 1, 'c': 1, 'd': 1, 'e': 1})
print(counter1 – counter2) # Counter({'b': 1, 'c': 1, 'a': 1})

Словари в функциональном программировании

Сочетание словарей с функциональными подходами:

Python
Скопировать код
# Трансформация словаря с map и lambda
prices = {'apple': 0.5, 'orange': 0.8, 'pear': 0.4}
dollar_to_euro = 0.85
euro_prices = dict(map(lambda item: (item[0], item[1] * dollar_to_euro), prices.items()))

# Фильтрация словаря с dict comprehension
expensive = {k: v for k, v in prices.items() if v > 0.6}

# Редукция (сложение всех значений)
total_price = sum(prices.values())

Продвинутая работа со словарями в Python открывает широкие возможности для элегантного решения сложных задач. Освоив эти техники, вы сможете значительно улучшить качество своего кода и эффективно решать задачи обработки данных.

Решение практических задач с использованием словарей

Теория без практики — всего лишь абстракция. Давайте рассмотрим реальные сценарии, где словари Python демонстрируют свою мощь в решении повседневных задач программирования. 💪

Задача 1: Подсчет частоты слов в тексте

Python
Скопировать код
def count_words(text):
words = text.lower().split()
word_count = {}
for word in words:
# Удаляем пунктуацию
word = word.strip('.,!?:;()"\'')
if word:
word_count[word] = word_count.get(word, 0) + 1
return word_count

text = "To be, or not to be, that is the question."
frequencies = count_words(text)
print(frequencies)
# {'to': 2, 'be': 2, 'or': 1, 'not': 1, 'that': 1, 'is': 1, 'the': 1, 'question': 1}

Задача 2: Группировка данных

Python
Скопировать код
def group_by_department(employees):
departments = {}
for employee in employees:
dept = employee['department']
if dept not in departments:
departments[dept] = []
departments[dept].append(employee['name'])
return departments

employees = [
{'name': 'Alice', 'department': 'Development'},
{'name': 'Bob', 'department': 'HR'},
{'name': 'Charlie', 'department': 'Development'},
{'name': 'Diana', 'department': 'Marketing'}
]

grouped = group_by_department(employees)
print(grouped)
# {'Development': ['Alice', 'Charlie'], 'HR': ['Bob'], 'Marketing': ['Diana']}

Задача 3: Кэширование результатов функций (мемоизация)

Python
Скопировать код
def memoize(func):
"""Декоратор для кэширования результатов функции"""
cache = {}
def wrapper(*args):
if args in cache:
return cache[args]
result = func(*args)
cache[args] = result
return result
return wrapper

@memoize
def fibonacci(n):
if n <= 1:
return n
return fibonacci(n-1) + fibonacci(n-2)

# Без кэширования это заняло бы значительно больше времени
print(fibonacci(35)) # 9227465

Задача 4: Построение графа и обход в ширину

Python
Скопировать код
from collections import deque

def build_graph(edges):
"""Построение графа из списка рёбер"""
graph = {}
for a, b in edges:
if a not in graph:
graph[a] = []
if b not in graph:
graph[b] = []
graph[a].append(b)
graph[b].append(a) # Для неориентированного графа
return graph

def bfs(graph, start):
"""Обход графа в ширину"""
visited = {start}
queue = deque([start])
result = []

while queue:
vertex = queue.popleft()
result.append(vertex)

for neighbor in graph[vertex]:
if neighbor not in visited:
visited.add(neighbor)
queue.append(neighbor)

return result

edges = [('A', 'B'), ('A', 'C'), ('B', 'D'), ('C', 'D'), ('C', 'E')]
graph = build_graph(edges)
print(bfs(graph, 'A')) # ['A', 'B', 'C', 'D', 'E']

Задача 5: Реализация LRU-кэша (Least Recently Used)

Python
Скопировать код
class LRUCache:
def __init__(self, capacity):
self.capacity = capacity
self.cache = {}
self.order = []

def get(self, key):
if key in self.cache:
# Обновляем порядок использования
self.order.remove(key)
self.order.append(key)
return self.cache[key]
return -1

def put(self, key, value):
if key in self.cache:
self.order.remove(key)
elif len(self.cache) >= self.capacity:
# Удаляем наименее недавно использованный элемент
oldest = self.order.pop(0)
del self.cache[oldest]

self.cache[key] = value
self.order.append(key)

cache = LRUCache(2)
cache.put(1, 1)
cache.put(2, 2)
print(cache.get(1)) # 1
cache.put(3, 3) # удаляет ключ 2
print(cache.get(2)) # -1 (не найден)

Мария Воронцова, Python Team Lead В прошлом году мы столкнулись с серьезной проблемой производительности в системе анализа клиентских данных. Система обрабатывала миллионы транзакций, и критический компонент — агрегация по клиентам — стал узким местом. Изначально данные хранились в виде списка словарей транзакций. Для каждого отчета нам приходилось многократно итерировать по всему списку. Когда время генерации отчетов выросло до нескольких часов, мы решили переработать структуру данных. Мы создали словарь, где ключами были ID клиентов, а значениями — вложенные словари с агрегированной статистикой. Время формирования отчетов сократилось с часов до секунд! Словари Python спасли проект, а я получила повышение. Этот опыт научил меня тому, что правильный выбор структуры данных иногда важнее любой оптимизации алгоритма.

Задача 6: Реализация JSON-подобной структуры данных

Python
Скопировать код
class JsonObject:
def __init__(self, data=None):
self._data = {} if data is None else data

def __getattr__(self, key):
if key in self._data:
value = self._data[key]
if isinstance(value, dict):
return JsonObject(value)
return value
raise AttributeError(f"'{self.__class__.__name__}' object has no attribute '{key}'")

def __setattr__(self, key, value):
if key == "_data":
super().__setattr__(key, value)
else:
self._data[key] = value

def to_dict(self):
return self._data

# Использование
user = JsonObject()
user.name = "John Doe"
user.contact = JsonObject()
user.contact.email = "john@example.com"
user.contact.phone = "123-456-7890"

print(user.name) # John Doe
print(user.contact.email) # john@example.com
print(user.to_dict()) # {'name': 'John Doe', 'contact': {'email': 'john@example.com', 'phone': '123-456-7890'}}

Такие практические примеры демонстрируют универсальность и эффективность словарей в Python. Они могут служить основой для реализации сложных алгоритмов и структур данных, значительно упрощая код и повышая его производительность. Освоение работы со словарями — важнейший навык для перехода от новичка к продвинутому Python-разработчику.

Оптимизация и профессиональные приемы работы со словарями

Профессионалы отличаются от новичков не только знанием синтаксиса, но и пониманием внутренних механизмов работы инструментов. Рассмотрим продвинутые техники оптимизации работы со словарями в Python, которые сделают ваш код более эффективным и элегантным. 🚀

Оптимизация производительности

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

Python
Скопировать код
# Предварительное выделение размера (только для CPython)
# Предотвращает многократное изменение размера словаря
from collections import defaultdict

# Менее эффективно (много ресайзов)
slow_dict = {}
for i in range(10000000):
key = i % 1000
if key not in slow_dict:
slow_dict[key] = 0
slow_dict[key] += 1

# Более эффективно (избегаем проверок и ресайзов)
fast_dict = defaultdict(int)
for i in range(10000000):
fast_dict[i % 1000] += 1

Преимущества неизменяемых ключей

Python требует, чтобы ключи словаря были хешируемыми (обычно неизменяемыми). Это не просто ограничение, а важный механизм оптимизации:

Python
Скопировать код
# Используйте кортежи вместо списков для составных ключей
locations = {
('New York', 'USA'): {'population': 8.4e6, 'timezone': 'EST'},
('Tokyo', 'Japan'): {'population': 1.4e7, 'timezone': 'JST'}
}

# Для более сложных случаев используйте frozenset
# Когда порядок элементов не важен
tags1 = frozenset(['python', 'optimization'])
tags2 = frozenset(['optimization', 'python']) # Тот же хеш!

tag_stats = {
tags1: 24 # tags2 будет считаться тем же ключом
}

Вызов setdefault против паттерна ключ in словарь

Метод setdefault позволяет избежать двойного поиска ключа:

Python
Скопировать код
# Менее эффективно (два поиска ключа)
groups = {}
for name, group in [('Alice', 'admin'), ('Bob', 'user'), ('Charlie', 'admin')]:
if group not in groups:
groups[group] = []
groups[group].append(name)

# Более эффективно (один поиск ключа)
optimized = {}
for name, group in [('Alice', 'admin'), ('Bob', 'user'), ('Charlie', 'admin')]:
optimized.setdefault(group, []).append(name)

Уменьшение затрат памяти

Словари в Python могут потреблять значительный объем памяти. Вот несколько способов оптимизации:

Python
Скопировать код
# Использование __slots__ для классов, хранящихся в словарях
class Point:
__slots__ = ('x', 'y') # Предотвращает создание __dict__
def __init__(self, x, y):
self.x = x
self.y = y

# Для очень больших наборов данных рассмотрите специализированные структуры
import array
coords = {'points': array.array('d', [1\.0, 2.0, 3.0, 4.0])} # Более эффективно, чем список

# Для очень больших словарей с целочисленными ключами рассмотрите array.array или numpy

Профессиональные паттерны проектирования с использованием словарей

Словари являются основой для многих распространенных паттернов в Python:

Python
Скопировать код
# Паттерн "Стратегия" с использованием словаря функций
def add(x, y): return x + y
def subtract(x, y): return x – y
def multiply(x, y): return x * y
def divide(x, y): return x / y if y != 0 else float('inf')

operations = {
'+': add,
'-': subtract,
'*': multiply,
'/': divide
}

# Использование
def calculate(a, op, b):
return operations[op](a, b)

print(calculate(10, '+', 5)) # 15
print(calculate(10, '*', 5)) # 50

Сортировка словарей

Часто требуется получить данные из словаря в определенном порядке:

Python
Скопировать код
scores = {'Alice': 95, 'Bob': 87, 'Charlie': 92, 'David': 78}

# Сортировка по ключам
sorted_by_name = dict(sorted(scores.items()))

# Сортировка по значениям (по убыванию)
sorted_by_score = dict(sorted(scores.items(), key=lambda x: x[1], reverse=True))

# Для более сложных случаев, используйте operator.itemgetter
from operator import itemgetter
students = [
{'name': 'Alice', 'grade': 'A', 'score': 95},
{'name': 'Bob', 'grade': 'B', 'score': 87},
{'name': 'Charlie', 'grade': 'A', 'score': 92}
]

# Сортировка сначала по grade, затем по score
sorted_students = sorted(students, key=itemgetter('grade', 'score'), reverse=True)

Сравнение эффективности различных подходов к работе со словарями:

Операция Наивный подход Оптимизированный подход Прирост производительности
Проверка и вставка if key not in dict: dict[key] = [] dict.setdefault(key, []) ~15-20% быстрее
Подсчет элементов Ручное увеличение счетчика collections.Counter ~40-50% быстрее
Объединение словарей Циклы и обновление dict1 | dict2 (Python 3.9+) ~30% быстрее
Преобразование словаря Создание нового словаря в цикле Словарное включение ~25-35% быстрее
Агрегация по ключам Вложенные циклы itertools.groupby ~60-70% быстрее для больших наборов
Группировка элементов Ручное создание групп defaultdict(list) ~30-40% быстрее

Работа со словарями в многопоточной среде

При использовании словарей в многопоточной среде следует учитывать вопросы синхронизации:

Python
Скопировать код
import threading

# Проблема гонки данных
shared_dict = {}
def update_unsafe(key, value):
shared_dict[key] = value

# Решение с блокировкой
lock = threading.Lock()
def update_safe(key, value):
with lock:
shared_dict[key] = value

# Альтернативный подход — использование thread-safe структур данных
from queue import Queue
message_queue = Queue()

Профилирование и измерение производительности

Прежде чем оптимизировать, важно измерить производительность:

Python
Скопировать код
import timeit
import cProfile

# Сравнение скорости разных методов доступа
setup = "data = {'key': 'value'}"

print(timeit.timeit("x = data['key']", setup=setup, number=1000000))
print(timeit.timeit("x = data.get('key')", setup=setup, number=1000000))

# Для более сложных сценариев используйте cProfile
def process_large_dict():
large_dict = {i: i*i for i in range(100000)}
result = {}
for k, v in large_dict.items():
if v % 3 == 0:
result[k] = v
return result

cProfile.run('process_large_dict()')

Используя эти профессиональные приемы и методы оптимизации, вы сможете значительно повысить эффективность вашего кода, особенно при работе с большими объемами данных. Понимание внутренних механизмов словарей в Python — это то, что отличает опытного разработчика от новичка.

Работа со словарями — фундаментальный навык для каждого Python-разработчика. От простого хранения данных до сложной оптимизации алгоритмов, словари предлагают гибкий и мощный инструмент, который растет вместе с вашим опытом. Освоив основы, вы создаете прочный фундамент; изучив продвинутые техники, вы строите изящные решения; а применяя профессиональные приемы оптимизации, вы создаете высокопроизводительный код, способный масштабироваться для самых сложных задач. Если вы стремитесь стать настоящим Python-профессионалом, глубокое понимание словарей — это не просто полезный навык, а обязательное требование.

Читайте также

Проверь как ты усвоил материалы статьи
Пройди тест и узнай насколько ты лучше других читателей
Что такое словари в Python?
1 / 5

Загрузка...