🐛 Типичные ошибки

⚡ Топ-3 ошибки

  • Путать print и return — результат оказывается None.
  • Думать, что аннотации типов проверяются во время выполнения.
  • Изменять изменяемый аргумент внутри функции без копии.

❌ Ошибка 1: Путать print и return при аннотации результата

# Неправильно: функция аннотирована как возвращающая str, но возвращает None
def greet(name: str) -> str:
    print(f"Hello, {name}!")

result = greet("Alice")
print(result.upper())  # AttributeError: 'NoneType' object has no attribute 'upper'

Сообщение об ошибке: AttributeError: 'NoneType' object has no attribute 'upper'

Почему возникает: функция без явного return возвращает None. Аннотация -> str не заставляет функцию вернуть строку — это лишь подсказка.

✅ Исправление

# Правильно
def greet(name: str) -> str:
    return f"Hello, {name}!"

result = greet("Alice")
print(result.upper())

❌ Ошибка 2: Думать, что аннотации проверяются во время выполнения

# Неправильно: Python не выдаст ошибку, хотя переданы строки
def add(a: int, b: int) -> int:
    return a + b

print(add("3", "5"))  # "35" — неожиданный результат

Почему возникает: Python остаётся динамически типизированным. Аннотации нужны для IDE и статических анализаторов, но интерпретатор ими пренебрегает.

✅ Исправление

Передавайте аргументы правильных типов. Для автоматической проверки используйте mypy или аналогичные инструменты.

print(add(3, 5))  # 8

❌ Ошибка 3: Изменять изменяемый аргумент внутри функции без копии

# Неправильно: функция меняет оригинальный список
def add_suffix(items: list[str]) -> None:
    items.append("suffix")

my_items = ["a", "b"]
add_suffix(my_items)
print(my_items)  # ['a', 'b', 'suffix'] — оригинал изменился

Почему возникает: список передаётся по ссылке, поэтому append меняет общий объект.

✅ Исправление

# Правильно: работаем с копией
def add_suffix(items: list[str]) -> list[str]:
    new_items = items.copy()
    new_items.append("suffix")
    return new_items

my_items = ["a", "b"]
result = add_suffix(my_items)
print(my_items)  # ['a', 'b']
print(result)    # ['a', 'b', 'suffix']

❌ Ошибка 4: Использовать изменяемый объект как значение по умолчанию

# Неправильно: значение по умолчанию создаётся один раз
def append_item(item: str, items: list[str] = []) -> list[str]:
    items.append(item)
    return items

print(append_item("a"))  # ['a']
print(append_item("b"))  # ['a', 'b'] — неожиданно!

Почему возникает: значения по умолчанию вычисляются при определении функции, а не при каждом вызове. Один и тот же список используется повторно.

✅ Исправление

# Правильно: None как значение по умолчанию
def append_item(item: str, items: list[str] | None = None) -> list[str]:
    if items is None:
        items = []
    items.append(item)
    return items

print(append_item("a"))  # ['a']
print(append_item("b"))  # ['b']

❌ Ошибка 5: Путать tuple[str, int] и list[str]

# Неправильно: ожидается кортеж фиксированной длины, а передан список
def get_pair() -> tuple[str, int]:
    return ["answer", 42]  # mypy укажет на несоответствие

Почему возникает: tuple[str, int] описывает ровно два элемента фиксированных типов, а list[str] — список произвольной длины со строками.

✅ Исправление

# Правильно
def get_pair() -> tuple[str, int]:
    return "answer", 42