Тип значения в Python: базовые концепции
Основные методы определения типа значения
Как узнать тип объекта в Python?
Самый прямой способ - вызов функции type(). Она возвращает объект типа, который можно вывести на экран или сравнить с известным классом. Например, type(42) вернет <class 'int'>. Функция работает для любых объектов, включая функции, модули и пользовательские классы.
x = 3.14
print(type(x)) # <class 'float'>
print(type(x) is float) # TrueSet str python (множество из строки в python)
Как проверить, принадлежит ли объект определённому типу или его подклассу?
Для проверки с учётом наследования используется isinstance(). Функция принимает объект и класс (или кортеж классов) и возвращает True, если объект является экземпляром любого из них.
class Shape: pass
class Circle(Shape): pass
c = Circle()
print(isinstance(c, Shape)) # True
print(isinstance(c, (int, Shape))) # TruePython переменная время (переменные для времени в python)
Типичная ошибка: игнорирование наследования
При использовании type(obj) is ParentClass для экземпляра подкласса результат будет False, что часто не соответствует ожиданиям. Всегда применяйте isinstance, если требуется проверка принадлежности к иерархии.
Какие существуют альтернативные способы определения типа?
Помимо type и isinstance, доступны следующие варианты:
- Атрибут
__class__- хранит ссылку на класс экземпляра.obj.__class__эквивалентноtype(obj)для обычных объектов, но может вести себя иначе для встроенных типов (например, для экземпляровtype). - Модуль
typing- функцияget_type_hints()позволяет извлечь аннотации типов из функций и классов, что полезно для статического анализа. - Преобразование (приведение) типов - с помощью функций
int(),str(),float()и т.д. можно изменить тип значения. Ошибки преобразования вызываютTypeErrorилиValueError. - Сравнение с классом через оператор
is-type(obj) is SomeClass- строгая проверка без учёта подклассов.
Как определить тип возвращаемого значения функции?
После вызова функции можно применить type() или isinstance() к результату. Если функция имеет аннотацию возвращаемого типа, её можно получить через typing.get_type_hints(func).
def get_data(flag):
if flag:
return 42
else:
return 'text'
result = get_data(True)
print(type(result)) # <class 'int'>
from typing import get_type_hints
hints = get_type_hints(get_data)
print(hints.get('return')) # Union[int, str]Python объект тип (тип объекта в python)
Проблема: неоднозначный тип при нескольких return
Когда функция возвращает разные типы, необходимо проверять конкретный тип полученного значения перед использованием. Игнорирование такой проверки может привести к TypeError при попытке выполнить операцию, не поддерживаемую для данного типа.
value = get_data(False)
print(value.upper()) # 'TEXT' - если строка, но если число - AttributeError
Решение: перед вызовом метода проверить тип с помощью isinstance.
Как узнать тип переменной, не вызывая функцию?
Если переменная уже определена, достаточно использовать type() или __class__. Для проверки типа в условных конструкциях применяется isinstance.
Расширенные примеры работы с типами значений
Пример 1: Проверка типа аргументов декоратора
Декоратор может проверять типы переданных аргументов и вызывать исключение при несоответствии.
def typed_decorator(expected_type):
def decorator(func):
def wrapper(*args, **kwargs):
for arg in args:
if not isinstance(arg, expected_type):
raise TypeError(f'Argument {arg} is not {expected_type}')
return func(*args, **kwargs)
return wrapper
return decorator
@typed_decorator(int)
def add(a, b):
return a + b
print(add(1, 2)) # 3
# print(add(1, '2')) # TypeError
3
Пример 2: Различие между type() и isinstance() для булевых значений
Тип bool является подклассом int. Проверка через type() даёт точный класс, а isinstance учитывает наследование.
flag = True
print(type(flag) is bool) # True
print(type(flag) is int) # False
print(isinstance(flag, int)) # True
print(isinstance(flag, bool)) # True
True False True True
Пример 3: Приведение типов с обработкой ошибок
При преобразовании строки в число можно использовать блок try/except для перехвата ValueError и TypeError.
def safe_int(value):
try:
return int(value)
except (ValueError, TypeError) as e:
print(f'Ошибка преобразования: {e}')
return None
print(safe_int('123')) # 123
print(safe_int('abc')) # None
print(safe_int([1,2])) # None
123 Ошибка преобразования: invalid literal for int() with base 10: 'abc' None Ошибка преобразования: int() argument must be a string, a bytes-like object or a number, not 'list' None
Пример 4: Использование get_type_hints для проверки возвращаемого типа
Модуль typing позволяет извлечь аннотации типов. Можно динамически проверить, соответствует ли фактический результат аннотации.
from typing import get_type_hints, Union
def func(a: int, b: int) -> Union[int, str]:
if a + b > 10:
return 'big'
return a + b
hints = get_type_hints(func)
print('Return type hint:', hints.get('return'))
result = func(5, 3)
print('Result:', result)
print('Type matches hint?', isinstance(result, hints.get('return')))
Return type hint: typing.Union[int, str] Result: 8 Type matches hint? True
Пример 5: Проверка типа None
NoneType - отдельный тип. Частая ошибка - попытка вызвать метод у None. Проверка через isinstance(x, type(None)) или просто x is None.
value = None
print(type(value)) # <class 'NoneType'>
print(isinstance(value, type(None))) # True
if value is None:
print('Переменная не содержит значения')
<class 'NoneType'> True Переменная не содержит значения