⚖️ Старый и современный подход

⚡ Различия в двух словах

Из источника: ручное разбиение строк через split(",") и группировка через defaultdict.

Альтернатива: для сложных CSV лучше использовать модуль csv, а для учебных данных с простым форматом достаточно split.

Группировка: вложенные обычные словари требуют проверок if key not in dict, а defaultdict делает код короче и чище.

📜 Ручная группировка через обычные словари

Можно обойтись без defaultdict, но код становится длиннее из-за постоянных проверок ключей:

# manual_grouping.py
sales = [
    {"date": "2025-02-01", "amount": 100, "category": "Electronics"},
    {"date": "2025-02-02", "amount": 200, "category": "Electronics"},
]

grouped = {}
for record in sales:
    key = (record["date"][:4], record["date"][5:7], record["category"])
    if key not in grouped:
        grouped[key] = []
    grouped[key].append(record)

# Для сумм приходится делать двойную проверку
category_totals = {}
for record in sales:
    period = (record["date"][:4], record["date"][5:7])
    if period not in category_totals:
        category_totals[period] = {}
    if record["category"] not in category_totals[period]:
        category_totals[period][record["category"]] = 0
    category_totals[period][record["category"]] += record["amount"]

Этот код работает, но содержит много шаблонных проверок.

✅ Группировка через defaultdict

С defaultdict проверки исчезают — фабрика значений создаёт нужные структуры автоматически:

# defaultdict_grouping.py
from collections import defaultdict

sales = [
    {"date": "2025-02-01", "amount": 100, "category": "Electronics"},
    {"date": "2025-02-02", "amount": 200, "category": "Electronics"},
]

grouped = defaultdict(list)
category_totals = defaultdict(lambda: defaultdict(int))

for record in sales:
    key = (record["date"][:4], record["date"][5:7], record["category"])
    grouped[key].append(record)
    category_totals[(record["date"][:4], record["date"][5:7])][record["category"]] += record["amount"]
  • Меньше кода и меньше ошибок.
  • Легче читать и поддерживать.
  • Не нужно помнить об инициализации каждого уровня вложенности.

📜 Разбор строк через split(",")

В исходном задании строки разбираются через split(","). Это простой и понятный способ, если формат гарантированно простой:

# split_approach.py
line = "Olivia Suarez,2024-08-02,4565,Electronics,Dallas"
parts = line.strip().split(",")
name, date, amount, category, city = parts

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

✅ Разбор через модуль csv

Модуль csv корректно обрабатывает кавычки, запятые внутри полей и экранирование:

# csv_approach.py
import csv

with open("sales_data.csv", "r", encoding="utf-8", newline="") as file:
    reader = csv.reader(file)
    for row in reader:
        name, date, amount, category, city = row
⚠️ Проверить по документации: модуль csv не разбирается в исходной лекции, но является рекомендуемым инструментом для работы с настоящими CSV-файлами.

📜 Ручное склеивание путей

Начинающие иногда пишут пути вручную, что ломается при переносе на другую ОС:

# Неправильно
path = output_dir + "\\" + year + "\\" + month + "\\" + filename

✅ Кроссплатформенные пути через os.path.join

# Правильно
import os

path = os.path.join(output_dir, year, month, filename)

Этот код работает одинаково на Windows, Linux и macOS.

🕰️ Когда какой подход использовать

СитуацияРекомендуемый подход
Учебный файл с гарантированно простым форматом split(",") + defaultdict
Реальные CSV-файлы из внешних источников Модуль csv
Нужна группировка по нескольким уровням defaultdict или collections.Counter
Работа с путями в любом проекте os.path.join или pathlib.Path
⚠️ Проверить по документации: pathlib — современная объектно-ориентированная альтернатива os.path, не разбираемая в исходной лекции.