Интроспекция в Python

Замечание
Последний раз данная статья обновлялась 01.12.2022, информация может быть устаревшей.

Список вопросов к Python собеседованию

Интроспекция (introspection) в контексте объектно-ориентированных языков программирования — это возможность запросить тип и структуру объекта во время выполнения программы.

Среди языков, поддерживающих интроспекцию — C++ (с RTTI), Go, Java, Kotlin, JavaScript, Perl, Ruby, Smalltalk, PHP и Python.

В PHP и Python интроспекция интегрирована в сам язык.

В Python интроспекция может быть функционально реализована с помощью:

  • встроенных методов dir(), type(), isinstance(), hasattr(), id();
  • встроенного модуля inspect;
  • идти непосредственно от имени объекта с помощью встроенных аттрибутов __class__ и __dict__.

Пользоваться интроспекцией в Python особенно удобно, благодаря парадигме, что “всё является объектом”. Любая сущность, являясь объектом, имеет метаданные (данные об объекте), называемые аттрибутами, и связаные с этой сущностью функциональности, называемые методами. В Python новый класс по-умолчанию является сам по себе объектом метакласса type.

Наиболее часто используемые функции интроспекции в Python:

  • Предоставляет список атрибутов и методов, доступных для указанного объекта, который может быть объявленной переменной или функцией.
  • Возвращаемое значение это отсортированный в алфавитном порядке список.
  • При вызове функции dir() без аргумента она возвращает имена, доступные в локальной области видимости.
1
2
a = [1, 2, 3]
dir(a)  # ['__add__', '__class__', '__contains__', ... , 'sort']

Возвращает тип объекта, который может быть примитивным типом данных, объектом, классом или модулем.

Можно напрямую сравнить возвращаемое значение с типом, который мы хотим проверить, используя == или is.

1
2
3
type(8.7)  # <class 'float'>
type("test") == int  # False
type((7, 5,)) is tuple  # True

Позволяет определить, является ли определенный объект экземпляром указанного класса.

isinstance() может принимать кортеж в качестве второго аргумента,

1
2
3
isinstance([1,2], list)  # True
isinstance([1,2], tuple)  # False
isinstance(1, (int, float, tuple))  # True
type() vs isinstance()

При использовании type() проводится сравнение один к одному. По сути, мы сравниваем тип объекта с типом, который мы указали, чтобы проверить, совпадают ли они.

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

Функция hasattr() проверяет существование атрибута с именем name в объекте object. Возвращает True, если атрибут существует, иначе False.

Реализация функция hasattr() основывается на вызове функции getattr() с последующей проверкой на предмет брошенного ей исключения AttributeError.

1
2
3
x = ('one', 'two', 'boom')
hasattr(x, 'some_attr')  # False
hasattr(x, 'count')  # True

Функция id() возвращает уникальный идентификатор для указанного объекта.

1
2
x = ('one', 'two', 'boom')
id(x)  # 140575915669688

В CPython идентификатор объекта — это адрес объекта в памяти.

  • Все объекты в Python имеют свой уникальный идентификатор. Идентификатор присваивается объекту при его создании. Идентификатор является адресом памяти объекта и будет отличаться при каждом запуске программы.
  • Объекты могут иметь одинаковый идентификатор, если периоды их существования не пересекаются.
  • Некоторые объекты могут иметь один и тот же идентификатор, например: мелкие целые от -5 до 256, True и False.

Модуль inspect также предоставляет несколько полезных функций для получения информации об объектах. Например, можно проверить элементы объекта:

1
2
3
import inspect
print(inspect.getmembers(str))
# Output: [('__add__', <slot wrapper '__add__' of ... ...

Источники:

Wiki