2.33. Introspección

Un puñado de funciones incorporadas permiten que un programa en ejecución se inspeccione a sí mismo – los valores con los que trabaja, los espacios de nombres en los que viven esos valores y las relaciones entre clases. Recurre a ellas cuando necesites tomar decisiones basadas en lo que un objeto realmente es, en lugar de lo que quien lo llama afirma que es.

2.33.1. Identidad y hashing

  • id() – un entero único que identifica un objeto mientras esté vivo. Dos nombres que vinculan el mismo objeto devuelven el mismo id; dos objetos iguales pero distintos no.

>>> 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

El id no es portable entre ejecuciones y no tiene más significado que «mismo objeto u objeto distinto».

  • hash() – el valor hash de un objeto, el mismo número que dict y set usan para buscarlo. Dos objetos iguales producen el mismo hash; solo funcionan los tipos hashables (valores inmutables, en su mayoría).

>>> hash("abc")           # some integer, build-dependent
-1600925533
>>> hash([1, 2])
TypeError: unhashable type: 'list'

2.33.2. Consultar tipos y la capacidad de ser llamado

  • type() – la clase exacta de un valor. type(x) is int pregunta «¿es x exactamente un int?» (sin subclases); isinstance() suele ser lo que quieres en su lugar.

  • isinstance() – «¿es x una instancia de esta clase, o de una subclase suya?» La herramienta estándar para el despacho basado en tipos dentro de funciones.

  • issubclass() – la contraparte a nivel de clases. Toma dos clases en lugar de una instancia.

  • callable()True si el argumento puede llamarse con (). Útil cuando recibes un argumento que puede ser una función o puede ser un valor simple.

>>> isinstance(3, int)
True
>>> isinstance(True, int)        # bool is a subclass of int
True
>>> issubclass(bool, int)
True
>>> callable(len)
True
>>> callable(10)
False

Un patrón que usa callable:

def call_or_return(x):
    return x() if callable(x) else x

2.33.3. Examinar los ámbitos

  • globals() – el espacio de nombres global del módulo como un dict. Leer de él funciona; escribir en él es real, pero hacerlo fuera de la exploración en el REPL hace que un programa sea difícil de seguir.

  • locals() – el espacio de nombres local en el punto de la llamada. Dentro de una función refleja las variables locales; modificar el diccionario devuelto no garantiza que se escriba de vuelta en las locales reales (comportamiento definido por la implementación).

name = "OpenMV"

def f():
    x = 10
    print(globals()["name"])    # OpenMV
    print(locals())             # {'x': 10}

Estas dos son útiles para depurar y para herramientas que necesitan descubrir qué está definido. Recurre a ellas con moderación en código normal – una función que muta globals() es una de las cosas más difíciles de razonar en Python.

2.33.4. Véase también

dir() y help(), tratadas en depuración, son las herramientas de introspección de uso diario para explorar la superficie de un objeto desconocido.