Python type(): как узнать и проверить тип переменной
Функция type() в Python
Основное назначение
Функция type() возвращает тип объекта. Это встроенная функция, которая принимает один аргумент и возвращает объект типа type, представляющий класс переданного объекта.
x = 42
type(x) # <class 'int'>Python получить тип переменной (определение типа переменной в python)
Результат можно использовать для сравнения, проверки принадлежности к классу или динамического создания объектов.
Как узнать тип переменной во время выполнения?
С помощью type() с одним аргументом:
print(type(3.14)) # <class 'float'>
print(type('abc')) # <class 'str'>тип данных type python (функция type() в python)
Типичная ошибка
Новинки путают type() и isinstance(). type() не учитывает наследование. Если класс B наследует от A, то type(B()) вернет B, а isinstance(B(), A) вернет True.
Как создать класс динамически с помощью type()?
Функция type() с тремя аргументами создает новый класс. Первый аргумент - имя класса, второй - кортеж базовых классов, третий - словарь атрибутов и методов.
MyClass = type('MyClass', (object,), {'x': 10, 'foo': lambda self: self.x})
obj = MyClass()
print(obj.foo()) # 10Проблема
Если забыть передать базовые классы (второй аргумент), класс будет без предков. Обычно указывают (object,) для новых стилей классов в Python 2, в Python 3 это не обязательно, но рекомендуется.
Как проверить, является ли объект экземпляром точного класса (не подкласса)?
Используется сравнение type(obj) is ClassName или type(obj) == ClassName. Это отличается от isinstance().
class Animal:
pass
class Dog(Animal):
pass
d = Dog()
print(type(d) is Dog) # True
print(type(d) is Animal) # False (так как тип Dog)
print(isinstance(d, Animal)) # TrueКак получить имя типа в виде строки?
Можно использовать атрибут __name__ объекта типа, возвращенного type():
value = 3.14
type_name = type(value).__name__
print(type_name) # 'float'Или напрямую data.__class__.__name__.
Как отличить type() от isinstance() при работе с пользовательскими классами?
Выбор зависит от задачи. Если требуется точное совпадение типа (игнорируя подклассы), используйте type(). Если нужно включить подклассы, используйте isinstance().
class Base:
pass
class Derived(Base):
pass
d = Derived()
print(type(d) == Base) # False
print(isinstance(d, Base)) # TrueКак использовать type() для проверки нескольких типов?
Можно сравнить с кортежем типов, но для этого лучше подходит isinstance():
x = 5
if type(x) in (int, float):
print('число') # выведет
# или через isinstance
if isinstance(x, (int, float)):
print('число')Частая ошибка
Использование type(x) is str вместо isinstance(x, str) при работе с наследованием. Например, если унаследовать от str, type() вернет подкласс, а не str, что может быть неожиданным.
Как определить тип None?
type(None) возвращает <class 'NoneType'>.
print(type(None)) # <class 'NoneType'>Расширенные примеры использования type()
Пример 1: Динамическое создание класса с методами и атрибутами
def say_hello(self):
return 'Привет, ' + self.name
Person = type('Person', (object,), {
'name': 'Аноним',
'greet': say_hello
})
p = Person()
print(p.greet()) # 'Привет, Аноним'
# Изменение атрибута
p.name = 'Иван'
print(p.greet()) # 'Привет, Иван'Привет, Аноним Привет, Иван
Пример 2: Использование type() для проверки аргументов функции
def process_data(data):
if type(data) == list:
print('Передан список')
elif type(data) == dict:
print('Передан словарь')
else:
print(f'Неизвестный тип: {type(data).__name__}')
process_data([1, 2])
process_data({'a': 1})
process_data(42)Передан список Передан словарь Неизвестный тип: int
Пример 3: type() с тремя аргументами – создание класса с наследованием и переопределением методов
class Base:
def work(self):
return 'Base work'
Derived = type('Derived', (Base,), {
'work': lambda self: 'Derived work'
})
d = Derived()
print(d.work()) # 'Derived work'
print(isinstance(d, Base)) # TrueDerived work True
Пример 4: Получение метакласса с помощью type()
class Meta(type):
pass
class MyClass(metaclass=Meta):
pass
print(type(MyClass)) # <class '__main__.Meta'>
print(type(MyClass) is Meta) # True<class '__main__.Meta'> True
Пример 5: Использование type() в декораторе для проверки типа возвращаемого значения
import functools
def ensure_type(expected_type):
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
result = func(*args, **kwargs)
if not isinstance(result, expected_type):
raise TypeError(f'Ожидался {expected_type}, получен {type(result)}')
return result
return wrapper
return decorator
@ensure_type(int)
def add(a, b):
return a + b
print(add(2, 3)) # 5
# add(2, '3') вызовет ошибку, но уже в вычислении, до проверки5
Пример 6: Сравнение type() и isinstance() на иерархии классов
class A: pass
class B(A): pass
class C(B): pass
c = C()
print('type(c) is A:', type(c) is A) # False
print('type(c) is B:', type(c) is B) # False
print('type(c) is C:', type(c) is C) # True
print('isinstance(c, A):', isinstance(c, A)) # True
print('isinstance(c, B):', isinstance(c, B)) # True
print('isinstance(c, C):', isinstance(c, C)) # Truetype(c) is A: False type(c) is B: False type(c) is C: True isinstance(c, A): True isinstance(c, B): True isinstance(c, C): True
Пример 7: type() для экземпляров встроенных типов и пользовательских
data = [1, 2, 3]
print(type(data)) # <class 'list'>
print(type(data) is list) # True
class MyList(list):
pass
ml = MyList([4,5])
print(type(ml)) # <class '__main__.MyList'>
print(type(ml) is list) # False (хотя isinstance вернет True)<class 'list'> True <class '__main__.MyList'> False
Пример 8: Использование type() для создания анонимных классов в рантайме
def make_class(name, base, attrs):
return type(name, (base,), attrs)
MyClass = make_class('MyClass', object, {'x': 100, 'show': lambda self: self.x})
obj = MyClass()
print(obj.show()) # 100
print(type(obj).__name__) # 'MyClass'100 MyClass