2.33. Интроспекция¶
Несколько встроенных функций позволяют работающей программе исследовать саму себя – значения, с которыми она работает, пространства имён, в которых эти значения живут, и отношения между классами. Прибегайте к ним, когда нужно принимать решения на основе того, чем объект действительно является, а не того, чем его называет вызывающая сторона.
2.33.1. Идентичность и хеширование¶
id()– уникальное целое число, идентифицирующее объект всё то время, пока он жив. Два имени, связанные с одним и тем же объектом, возвращают один и тот же id; два равных, но различных объекта – нет.
>>> a = [1, 2, 3]
>>> b = a
>>> c = [1, 2, 3]
>>> id(a) == id(b) # same list
True
>>> id(a) == id(c) # equal but distinct
False
id не переносим между запусками и не имеет смысла, кроме как «тот же объект или другой объект».
hash()– хеш-значение объекта, то же число, котороеdictиsetиспользуют для его поиска. Два равных объекта хешируются в одно и то же значение; вообще работают только хешируемые типы (в основном неизменяемые значения).
>>> hash("abc") # some integer, build-dependent
-1600925533
>>> hash([1, 2])
TypeError: unhashable type: 'list'
2.33.2. Запрос типов и вызываемости¶
type()– точный класс значения.type(x) is intспрашивает «является ли x в точности int» (без подклассов);isinstance()обычно является тем, что вам нужно вместо этого.isinstance()– «является ли x экземпляром этого класса или его подкласса?» Стандартный инструмент для диспетчеризации на основе типов внутри функций.issubclass()– аналог на уровне классов. Принимает два класса, а не экземпляр.callable()–True, если аргумент можно вызвать с помощью(). Полезно, когда вы получаете аргумент, который может быть функцией или может быть обычным значением.
>>> isinstance(3, int)
True
>>> isinstance(True, int) # bool is a subclass of int
True
>>> issubclass(bool, int)
True
>>> callable(len)
True
>>> callable(10)
False
Шаблон, использующий callable:
def call_or_return(x):
return x() if callable(x) else x
2.33.3. Просмотр областей видимости¶
globals()– глобальное пространство имён модуля в видеdict. Чтение из него работает; запись в него реальна, но за пределами исследования в REPL это делает программу трудной для понимания.locals()– локальное пространство имён в месте вызова. Внутри функции оно отражает локальные переменные; изменение возвращённого словаря не гарантированно записывается обратно в фактические локальные переменные (поведение, определяемое реализацией).
name = "OpenMV"
def f():
x = 10
print(globals()["name"]) # OpenMV
print(locals()) # {'x': 10}
Эти две функции полезны для отладки и для инструментов, которым нужно обнаружить, что определено. Прибегайте к ним в обычном коде экономно – функция, которая изменяет globals(), относится к самым трудным для понимания вещам в Python.
2.33.4. См. также¶
dir() и help(), описанные в debugging, – это повседневные инструменты интроспекции для исследования поверхности незнакомого объекта.