Метка: утиная типизация

Узнать тип type() и проверить тип isinstance()

В Python у нас утиная динамическая типизация, поэтому бывает что нужно узнать тип переменной. Функция type() возвращает тип аргумента или, учитывая, что в Python – все класс, то класс аргумента. Результат можно сравнить с известным типом:

>>> i, s = 10, "hello"
>>> type(i)
<class 'int'>
>>> type(i) is int
True
>>> type(s) is str
True
>>> class A: pass
...
>>> a = A()
>>> type(a) is A
True

Можно создать экземпляр объекта того же класса, что и переменная:

>>> new_a = type(a)()
>>> type(new_a) == type(a)
True

⚠️ Нужно знать! type() не принимает во внимание наследование. Тип наследника отличается от типа родителя:

>>> class B(A): pass
...
>>> type(A()) is type(B())
False

Лучший способ проверить типы – функция isinstance(x, type) (instance англ. – экземпляр). Она возвращает True, если первый аргумент является экземпляром класса во втором аргументе:

>>> isinstance(i, int)
True
>>> isinstance(s, str)
True
>>> isinstance(a, A)
True

Функция поддерживает наследование:

class A: pass
class B(A): pass
b = B()
>>> isinstance(b, A)
True

И самое крутое: вторым аргументом допускается передать кортеж из типов, и isinstance вернет True, если хоть один из типов в кортеже подходит:

>>> isinstance(i, (int, float))
True
>>> isinstance(a, (A, B))
True

Загадка:

class A: ...
a = A()
class A: ...
print(isinstance(a, A))

Правильный ответ был False!

Объяснение. Динамическая натура Python позволяет переопределить класс во время интерпретации. Помните, как недавно я рассказывал про декораторы класса? Там мы подменяли один класс другим. Вот это из той же оперы. Тут мы подменили один класс, другим классом, отвязав имя А от старого класса и привязав его к новому. Старый класс А остался жив только как класс объекта в переменной a. Старого и нового классов разные адреса (id):

class A: ...
print(id(A))  # 140479777819720

a = A()

class A: ...
print(id(A))  # 140479777809672

isinstance(a, A)  # False

Специально для канала @pyway. Подписывайтесь на мой канал в Телеграм @pyway 👈