← Назад к вопросам
Что такое Python с точки зрения типизации?
1.0 Junior🔥 221 комментариев
#Python Core
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
# Что такое Python с точки зрения типизации
Python — динамически типизированный язык, но это более сложно, чем кажется.
1. Динамическая типизация
# Тип определяется в runtime, а не compile time
x = 5 # int
print(type(x)) # <class 'int'>
x = "hello" # Теперь x — это строка
print(type(x)) # <class 'str'>
x = [1, 2, 3] # Теперь x — это список
print(type(x)) # <class 'list'>
Переменная не привязана к типу — тип может меняться.
2. Утиная типизация (Duck Typing)
# "Если ходит как утка и крякает как утка, то это утка"
class Dog:
def make_sound(self):
return "Гав"
class Cat:
def make_sound(self):
return "Мяу"
class Phone:
def make_sound(self):
return "Звонок"
def play_sound(something):
# Не проверяем тип, просто вызываем метод
print(something.make_sound())
play_sound(Dog()) # Гав
play_sound(Cat()) # Мяу
play_sound(Phone()) # Звонок
# Все работает, хоть они и разные классы
Функция работает со ВСЕМИ объектами, у которых есть метод make_sound().
3. Слабая типизация
# Python пытается конвертировать типы неявно
# Неявное преобразование в некоторых операциях
print("5" * 3) # "555" — строка умножается
print(5 + 3.14) # 8.14 — int + float = float
print([1, 2] + [3]) # [1, 2, 3] — конкатенация списков
# Но не всегда
print("5" + 3) # TypeError: can only concatenate str (not "int") to str
Python позволяет гибкость, но не настолько слаб как JavaScript.
4. Type Hints (Аннотации типов)
От Python 3.5+ появились опциональные аннотации типов.
# Без аннотаций (работает, но неясно)
def add(a, b):
return a + b
# С аннотациями (тот же код, но яснее)
def add(a: int, b: int) -> int:
return a + b
# Аннотации не проверяются Python runtime
result = add("hello", "world") # "helloworld" — работает!
# Python не выбросит ошибку, даже если не соблюданы типы
5. Статическая проверка типов (Type Checking)
Для проверки типов используют отдельные инструменты:
# mypy — самый популярный type checker
from typing import List, Dict, Optional
def process_users(users: List[Dict[str, int]]) -> Optional[str]:
if not users:
return None
return users[0].get("name")
# mypy проверит это
# mypy check script.py
Запускается отдельно, Python это игнорирует.
Сравнение типизации
STATIЧНО ТИПИЗИРОВАННЫЕ (compile time):
- Java: int x = 5; x = "hello"; // Ошибка компиляции
- TypeScript: const x: number = 5; x = "hello"; // Ошибка
- C: int x = 5; x = "hello"; // Ошибка компиляции
ДИНАМИЧЕСКИ ТИПИЗИРОВАННЫЕ (runtime):
- Python: x = 5; x = "hello"; # Ok, работает
- JavaScript: let x = 5; x = "hello"; // Ok, работает
- Ruby: x = 5; x = "hello"; # Ok, работает
Примеры с type hints
Базовые типы
from typing import List, Dict, Tuple, Set, Optional
def greet(name: str) -> str:
return f"Hello, {name}"
def get_user_by_id(user_id: int) -> Optional[Dict[str, str]]:
# Может вернуть dict или None
if user_id > 0:
return {"id": str(user_id), "name": "John"}
return None
def process_items(items: List[str]) -> Tuple[int, List[str]]:
# Функция принимает список строк
# Возвращает кортеж (количество, список)
return (len(items), items)
def get_config() -> Dict[str, int]:
return {"timeout": 30, "retries": 3}
Сложные типы
from typing import Union, Callable, Any
# Union — может быть один из нескольких типов
def parse_value(value: Union[int, str]) -> str:
return str(value)
# Callable — функция
def apply_operation(x: int, y: int, op: Callable[[int, int], int]) -> int:
return op(x, y)
apply_operation(5, 3, lambda a, b: a + b) # 8
# Any — любой тип (используй редко)
def dangerous_function(value: Any) -> Any:
return value
Пользовательские типы
from typing import Protocol
from abc import ABC, abstractmethod
# Протокол (структурная типизация)
class Drawable(Protocol):
def draw(self) -> None:
...
class Circle:
def draw(self) -> None:
print("Drawing circle")
class Square:
def draw(self) -> None:
print("Drawing square")
def render(obj: Drawable) -> None:
obj.draw() # Работает для любого объекта с методом draw()
render(Circle()) # Ok
render(Square()) # Ok
# Традиционное наследование (номинативная типизация)
class Animal(ABC):
@abstractmethod
def sound(self) -> str:
pass
class Dog(Animal):
def sound(self) -> str:
return "Гав"
Когда type hints помогают
1. IDE автодополнение
def get_user(user_id: int) -> Dict[str, str]:
return {"name": "John", "email": "john@example.com"}
user = get_user(1)
user. # IDE подскажет: name, email, keys, values, etc.
2. Обнаружение ошибок
from typing import List
def sum_numbers(numbers: List[int]) -> int:
return sum(numbers)
result = sum_numbers([1, 2, "3"]) # mypy найдёт ошибку
3. Документация
# Вместо:
def create_user(name, email, age):
# Какие типы?
# Что возвращает?
pass
# Пиши:
def create_user(name: str, email: str, age: int) -> Dict[str, Any]:
# Понятно с первого взгляда
pass
Структурная vs Номинативная типизация
# НОМИНАТИВНАЯ (Java, C++) — нужно явное наследование
class Shape(ABC):
@abstractmethod
def area(self) -> float:
pass
class Circle(Shape): # Явно наследуется
def area(self) -> float:
return 3.14
shape: Shape = Circle() # Ok
# СТРУКТУРНАЯ (Python с Protocol) — "структура важнее имени"
class Drawable(Protocol):
def draw(self) -> None:
...
class Square:
def draw(self) -> None: # Не наследуется, но совпадает структура
pass
obj: Drawable = Square() # mypy одобрит
Практическое применение
# Проект без type hints (сложно поддерживать)
def process_data(data):
result = []
for item in data:
if item > 0:
result.append(item * 2)
return result
# Проект с type hints (понятнее)
from typing import List
def process_data(data: List[int]) -> List[int]:
result = []
for item in data:
if item > 0:
result.append(item * 2)
return result
Важно помнить
✅ Type hints — это просто подсказки для инструментов (mypy, PyCharm)
✅ Python runtime их игнорирует
✅ def func(x: int) -> str: не гарантирует, что x будет int
✅ Для проверки нужен отдельный инструмент (mypy, Pydantic, pytest)
def add_numbers(a: int, b: int) -> int:
return a + b
result = add_numbers("5", "10") # Работает! Возвращает "510"
# Python не выбросит ошибку, даже если нарушены type hints
# mypy найдёт это:
# error: Argument 1 to "add_numbers" has incompatible type "str"; expected "int"
Вывод
Python с точки зрения типизации:
- Динамически типизирован — типы проверяются в runtime
- Слабо типизирован — позволяет некоторые преобразования
- Утиная типизация — важна структура, не имя типа
- Опционально статично типизируется — через type hints и mypy
- Гибкий — ты выбираешь, когда использовать type hints