Python isinstance: как проверить тип переменной
Функция isinstance в Python проверяет, является ли объект экземпляром указанного класса или его наследника, и возвращает True или False. С ее помощью функции обрабатывают аргументы разных типов, валидируют входные данные и разбирают JSON. В статье показан синтаксис, проверка сразу нескольких типов, разница с type(), работа с абстрактными классами и типичные ошибки.

Содержание статьи
Синтаксис и параметры
Функция встроенная, импорт не нужен. Она принимает ровно два позиционных аргумента.
isinstance(obj, classinfo)obj- проверяемый объект: переменная, литерал, результат выражения;classinfo- класс, кортеж классов или, начиная с Python 3.10, объединение через|.
Результат True, если объект относится к указанному классу или к любому классу, унаследованному от него. Если второй аргумент не является классом, Python выбросит TypeError: isinstance() arg 2 must be a type, a tuple of types, or a union.
numbers = [1, 2, 3]
print(isinstance(numbers, list)) # True
print(isinstance(numbers, dict)) # False
print(isinstance("5", int)) # False - это строка
print(isinstance(5.0, float)) # TrueПеречень встроенных классов, которые чаще всего подставляют во второй аргумент, есть в статье типы данных в Python.
Проверка нескольких типов
Чтобы проверить принадлежность к одному из нескольких классов, передайте их кортежем. Достаточно совпадения с любым элементом, это аналог цепочки or.
def describe(value):
if isinstance(value, (int, float)):
return f"число {value}"
if isinstance(value, (list, tuple, set)):
return f"коллекция из {len(value)} элементов"
return f"другое: {type(value).__name__}"
print(describe(3.5)) # число 3.5
print(describe((1, 2))) # коллекция из 2 элементов
print(describe("текст")) # другое: strВ Python 3.10 и новее вместо кортежа можно написать объединение isinstance(value, int | float). Результат тот же, а запись совпадает с синтаксисом аннотаций типов. Кортежи допускаются вложенными: (int, (list, tuple)) тоже сработает.
Наследование и иерархия классов
Главное отличие isinstance() от сравнения типов в том, что она учитывает наследование. Объект дочернего класса считается экземпляром и родителя, и всех классов выше по иерархии, вплоть до object.
class Animal:
pass
class Dog(Animal):
pass
rex = Dog()
print(isinstance(rex, Dog)) # True
print(isinstance(rex, Animal)) # True - Dog наследует Animal
print(isinstance(rex, object)) # True - любой объект
print(isinstance(Animal(), Dog)) # FalseЭто позволяет писать код для базового класса, и он автоматически будет работать со всеми наследниками. Как строятся такие иерархии, описано в статье наследование классов.
Ловушка с bool и int
В Python тип bool унаследован от int, поэтому True и False проходят проверку на целое число. В функциях, которые должны принимать только числа, это приводит к незаметным ошибкам.
print(isinstance(True, int)) # True
def set_count(n):
if isinstance(n, bool) or not isinstance(n, int):
raise TypeError("нужно целое число")
return n
set_count(10) # 10
# set_count(True) -> TypeErrorisinstance() или type()
Сравнение type(x) == list или type(x) is list проверяет точное совпадение класса и не учитывает наследников. В большинстве задач это скорее недостаток, поэтому для проверок рекомендуют isinstance().
| Проверка | Учитывает наследование | Несколько типов | Когда применять |
|---|---|---|---|
isinstance(x, cls) | да | кортеж или | | обычная проверка аргументов |
type(x) is cls | нет | только через in | нужен строго конкретный класс |
issubclass(A, B) | да | кортеж или | | сравнение классов, а не объектов |
from collections import OrderedDict
d = OrderedDict(a=1)
print(isinstance(d, dict)) # True
print(type(d) is dict) # False - класс OrderedDict
print(issubclass(OrderedDict, dict)) # Trueissubclass() принимает первым аргументом класс, а не объект. Вызов issubclass(d, dict) закончится ошибкой TypeError.
Проверка по абстрактным классам
Иногда важен не конкретный тип, а поведение: можно ли перебрать объект циклом, поддерживает ли он обращение по ключу. Для этого во втором аргументе указывают абстрактные классы из модуля collections.abc или numbers.
from collections.abc import Iterable, Mapping
from numbers import Number
print(isinstance([1, 2], Iterable)) # True
print(isinstance("abc", Iterable)) # True - строка тоже перебирается
print(isinstance({"a": 1}, Mapping)) # True
print(isinstance(3 + 2j, Number)) # True - комплексное числоТак функция примет любой подходящий объект, включая пользовательские классы, без перечисления всех вариантов. Обратите внимание, что строка тоже итерируемая: если нужно отличить список от строки, проверяйте str отдельно и раньше.
Где isinstance() используют на практике
Частая задача - рекурсивный обход данных из JSON, где значение может оказаться словарем, списком или простым значением.
def count_leaves(data):
if isinstance(data, dict):
return sum(count_leaves(v) for v in data.values())
if isinstance(data, list):
return sum(count_leaves(v) for v in data)
return 1
print(count_leaves({"a": [1, 2], "b": {"c": 3}})) # 3Не стоит злоупотреблять проверками: если функция просто вызывает у объекта метод, обычно проще его вызвать и обработать возможную ошибку. Для разбора данных по структуре с Python 3.10 есть оператор match case, который делает те же проверки типов короче. А статический контроль типов до запуска программы обеспечивают аннотации типов и анализаторы вроде mypy. Описание функции приведено в документации Python.
Частые вопросы
Короткие ответы на вопросы о проверке типов через isinstance().
Как проверить, что переменная - число?
Для целых и дробных подойдет isinstance(x, (int, float)), для любых числовых типов, включая Decimal и complex, используйте numbers.Number. Не забудьте исключить bool, если он не нужен.
Как проверить, что значение равно None?
Не через isinstance(), а сравнением x is None. Это короче и считается стандартной записью.
Можно ли передать список классов вместо кортежа?
Нет. Второй аргумент должен быть классом, кортежем или объединением через |. Список вызовет TypeError, его нужно преобразовать: tuple(types).
Работает ли isinstance() с подсказками вроде list[int]?
Нет. Обобщенные типы с параметрами не поддерживаются, isinstance(x, list[int]) выдаст TypeError. Проверяйте сам контейнер, а элементы отдельно, например через all().