Функции isinstance и type для проверки типов данных

Курс по Python: https://stepik.org/course/100707

На этом занятии мы поговорим о функции isinstance(), с помощью которой можно выполнять проверку на принадлежность объекта определенным типам данных.

Например, объявим переменную:

a = 5

и для нее вызовем функцию isinstance(), следующим образом:

isinstance(a, int)

Увидим значение True, так как переменная a действительно ссылается на целочисленный объект. А вот если указать:

isinstance(a, float)

то уже будет возвращено значение False. Вот так в самом простом варианте работает эта функция. Но у нее есть один нюанс, связанный с булевым типом данных. Если определить переменную:

b = True

то, очевидно, функция:

isinstance(b, bool)

вернет значение True. Однако, если вместо bool записать int:

isinstance(b, int)

то тоже увидим True. Это связано с особенностью реализацией типа bool. Не буду углубляться в эти детали, здесь просто достаточно запомнить этот момент. Но тогда спрашивается, а как отличать тип bool от типа int? Если нужна строгая проверка на типы, то лучше использовать знакомую нам функцию type() с проверкой на равенство:

type(b) == bool

или, используя оператор is:

type(b) is bool

Эта функция различает булевы типы от целочисленных:

type(b) is int

Или, если мы хотим произвести множественную проверку, то воспользоваться оператором in:

type(b) in (bool, float, str)

Здесь мы сразу проверяем переменную b на три типа данных.

Сейчас у вас может возникнуть вопрос, зачем нужна функция isinstance(), если проверку типов можно делать функцией type()? В целом, они действительно очень похожи, но isinstance() в отличие от type() делает проверку с учетом иерархии наследования объектов и была разработана для проверки принадлежности объекта тому или иному классу:

Например, тип bool наследуется от int, поэтому isinstance() выдает True для обоих типов, когда b – булева переменная. А функция type() даст True только для типа bool. То есть, здесь проверка происходит без учета иерархии. (Я сейчас не буду углубляться и объяснять, что такое наследование – это уже раздел ООП и предмет отдельного курса).

Теперь, когда мы в целом познакомились с работой функции isinstance(), давайте рассмотрим следующий пример. Предположим, что у нас есть кортеж с произвольными данными:

data = (4.5, 8.7, True, "книга", 8, 10, -11, [True, False])

И наша задача вычислить сумму всех вещественных чисел этой коллекции. Для этого, очевидно, вначале каждый элемент кортежа нужно проверить на вещественный тип данных, а затем, выполнять суммирование. Я вначале сделаю это через обычный цикл for:

s = 0
for x in data:
    if isinstance(x, float):
        s += x
 
print(s)

Как видите, у нас получилась нужная сумма. Но эту же задачу можно реализовать лучше, с использованием ранее рассмотренной функции filter():

s = sum(filter(lambda x: isinstance(x, float), data))

Видите, все записано в одну строчку и, кроме того, работает быстрее, так как используются встроенные функции вместо цикла for.

А вот если мы попробуем вычислить сумму целочисленных значений, просто изменив тип данных:

s = sum(filter(lambda x: isinstance(x, int), data))

то увидим неверное значение 8, так как в коллекции data присутствует булево значение True, которое интерпретируется как целое число 1. Здесь лучше применять строгую проверку с использованием функции type():

s = sum(filter(lambda x: type(x) is int, data))

Теперь видим верное значение 7.

С помощью функции isinstance() можно делать и множественные проверки. Например, мы хотим определить, относится ли число к целому или вещественному типу данных? Для этого достаточно записать кортеж из этих типов:

a = 5.5
isinstance(a, (int, float))

Это эквивалентно записи:

isinstance(a, int) or isinstance(a, float)

Но первый вариант короче и потому чаще используется на практике.

Вот так в Python можно выполнять проверку типов данных для произвольных объектов. А также знаете отличия между работой функций isinstance() и type(). До встречи на следующем уроке.

Курс по Python: https://stepik.org/course/100707

Видео по теме