← Назад к вопросам

Откуда рекомендуется импортировать Callable в Python 3.10

2.0 Middle🔥 131 комментариев
#Python Core

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI29 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Откуда рекомендуется импортировать Callable в Python 3.10?

Краткий ответ

В Python 3.10 рекомендуется импортировать Callable из модуля collections.abc (абстрактные базовые классы), а не из typing. Это изменение произошло из-за эволюции типизации в Python и её переориентации на стандартные классы.

История изменений

Python < 3.9

В ранних версиях Python Callable импортировали только из typing:

from typing import Callable

def process(callback: Callable[[int], str]) -> None:
    pass

Это было единственным способом, так как в collections.abc не было универсального Callable для аннотирования.

Python 3.9

В Python 3.9 появилась возможность импортировать Callable из collections.abc, но typing.Callable ещё работал.

Python 3.10+

Рекомендуемый подход — импортировать из collections.abc:

from collections.abc import Callable

def process(callback: Callable[[int], str]) -> None:
    result = callback(42)
    print(result)

process(lambda x: f"Number: {x}")

Почему именно collections.abc?

1. Унификация типизации

Python переходит на использование стандартных классов вместо специальных типов из typing. Это делает код более прозрачным:

# Старый подход (typing)
from typing import Callable, List, Dict

def old_function(callback: Callable, items: List[str]) -> Dict[str, int]:
    pass

# Новый подход (встроенные типы + collections.abc)
from collections.abc import Callable

def new_function(callback: Callable, items: list[str]) -> dict[str, int]:
    pass

2. Согласованность с другими абстрактными типами

Другие абстрактные типы уже находятся в collections.abc:

from collections.abc import (
    Callable,      # Для функций
    Iterator,      # Для итераторов
    Sequence,      # Для последовательностей
    Mapping,       # Для словарей
    Set            # Для множеств
)

def handler(func: Callable[[str], int], items: Sequence[str]) -> Mapping[str, int]:
    return {item: func(item) for item in items}

3. Производительность

collections.abc.Callable — это «нативный» класс, который работает быстрее, чем специальный тип из typing.

Полный пример

from collections.abc import Callable, Iterator
from typing import TypeVar

T = TypeVar("T")

class EventEmitter:
    def __init__(self):
        self._handlers: dict[str, list[Callable]] = {}
    
    def on(self, event: str, callback: Callable[[any], None]) -> None:
        if event not in self._handlers:
            self._handlers[event] = []
        self._handlers[event].append(callback)
    
    def emit(self, event: str, *args) -> None:
        if event in self._handlers:
            for handler in self._handlers[event]:
                handler(*args)

# Использование
emitter = EventEmitter()
emitter.on("click", lambda x: print(f"Clicked: {x}"))
emitter.emit("click", "button")

Когда ещё используется typing.Callable?

В редких случаях, когда нужны продвинутые функции типизации из typing:

from typing import Callable, overload, TypeVar

T = TypeVar("T")

@overload
def apply(func: Callable[[int], int], value: int) -> int: ...

@overload
def apply(func: Callable[[str], str], value: str) -> str: ...

def apply(func, value):
    return func(value)

Однако даже здесь сам Callable лучше импортировать из collections.abc.

Практические рекомендации

  • Всегда используйте from collections.abc import Callable в Python 3.10+
  • Используйте встроенные типы list, dict вместо List, Dict из typing
  • Включите from __future__ import annotations для совместимости
  • Обновляйте линтер (mypy, pylint) до последних версий

Это делает код более читаемым, производительным и соответствует современным стандартам Python.