Как определить тип объекта в Python
Что проверяют
Знаете ли вы разницу между точным типом и принадлежностью к иерархии и понимаете ли, когда проверка типа вообще не нужна. Следом спрашивают про наследование, про bool и про то, проверяются ли аннотации типов во время выполнения.
Как отвечать
type(obj): точный класс объекта. Сравнивают черезtype(x) is int, и для подклассов это ложно;isinstance(obj, cls): учитывает наследование, принимает кортеж(int, float), а с Python 3.10 и объединениеint | float. Это вариант по умолчанию;issubclass(cls, base): то же самое для классов, а не экземпляров;- абстрактные классы из
collections.abc:isinstance(x, Mapping)илиIterableпроверяет поведение, а не конкретныйdict. ДляIterableиSizedдостаточно реализовать нужный метод, наследоваться не обязательно; typing.Protocolс@runtime_checkable:isinstanceпроверяет только наличие методов, но не их сигнатуры;- диспетчеризация по типу:
matchс шаблонами видаcase int():илиfunctools.singledispatchвместо длинной цепочкиif.
Упомяните, что Python поощряет утиную типизацию: вместо проверки «это список?» часто лучше вызвать нужный метод и обработать исключение (подход EAFP). Проверки типов уместны на границах: разбор входных данных, публичное API библиотеки, диспетчеризация.
Отдельно про аннотации: def f(x: int) интерпретатор не проверяет, это работа mypy или pyright до запуска. Для проверки во время выполнения нужны pydantic или явный isinstance.
Где спотыкаются
Пишут type(x) == Parent и удивляются, что экземпляр подкласса проверку не проходит. Заодно сравнивают через ==, хотя для классов принято is.
Забывают, что bool это подкласс int: isinstance(True, int) вернёт True. Функция, которая ждёт число, молча примет флаг, если явно не отсечь bool первой проверкой.
Пытаются проверить параметризованный тип: isinstance(x, list[int]) бросает TypeError. Проверить можно только list, а тип элементов придётся обходить вручную или отдать валидатору вроде pydantic.