Ir al contenido

Instancias

La clase ReflectionInstance es una utilidad de introspección diseñada para analizar objetos instanciados de Python en tiempo de ejecución. Proporciona una API completa para inspeccionar atributos, métodos, propiedades, metadatos y dependencias de cualquier instancia de una clase concreta definida por el usuario.

A diferencia de ReflectionConcrete, que opera sobre la definición de una clase (el tipo), ReflectionInstance trabaja directamente con un objeto ya instanciado, lo que permite acceder tanto a los atributos de la clase como a los atributos de instancia asignados en el constructor o durante la ejecución.

from orionis.services.introspection.instances.reflection import ReflectionInstance

La clase recibe una instancia de un objeto como parámetro. Se valida que sea una instancia válida de una clase definida por el usuario, no un tipo, un built-in ni una clase abstracta.

from orionis.services.introspection.instances.reflection import ReflectionInstance
class UserService:
"""Service for managing users."""
public_attr: int
def __init__(self, x: int = 10) -> None:
self.public_attr = x
self._protected_attr = "prot"
self.__private_attr = "priv"
def greet(self) -> str:
return f"Hello, user #{self.public_attr}"
service = UserService(42)
reflection = ReflectionInstance(service)

Los siguientes tipos de objetos no son aceptados y lanzarán excepciones:

# TypeError: una clase, no una instancia
ReflectionInstance(UserService)
# TypeError: instancia de tipo built-in
ReflectionInstance(42)
ReflectionInstance("hello")
# TypeError: None
ReflectionInstance(None)

La clase ReflectionInstance implementa el contrato IReflectionInstance, que define la interfaz completa para la introspección de instancias:

from orionis.services.introspection.instances.contracts.reflection import IReflectionInstance

Retorna la instancia original del objeto que se está reflejando.

instance = reflection.getInstance()
# Retorna el mismo objeto UserService pasado al constructor

Retorna la clase del objeto instanciado.

cls = reflection.getClass()
# <class 'UserService'>

Retorna el nombre de la clase como cadena de texto.

name = reflection.getClassName()
# "UserService"

Retorna el nombre del módulo donde está definida la clase.

module = reflection.getModuleName()
# "app.services.user_service"

Retorna el nombre completamente cualificado (módulo + clase).

fqn = reflection.getModuleWithClassName()
# "app.services.user_service.UserService"

Retorna el docstring de la clase de la instancia, o None si no tiene.

doc = reflection.getDocstring()
# "Service for managing users."

Retorna una tupla con las clases base directas de la clase de la instancia.

bases = reflection.getBaseClasses()
# (<class 'object'>,)

Retorna el código fuente de la clase completa o de un método específico. Retorna None si no está disponible.

# Código fuente de toda la clase
source = reflection.getSourceCode()
# Código fuente de un método específico
method_source = reflection.getSourceCode("greet")

Retorna la ruta del archivo donde está definida la clase, o None si no es determinable.

path = reflection.getFile()
# "/app/services/user_service.py"

Retorna un diccionario con las anotaciones de tipo de la clase. Resuelve automáticamente el name mangling en atributos privados.

annotations = reflection.getAnnotations()
# {"public_attr": <class 'int'>}

ReflectionInstance clasifica los atributos de la instancia por nivel de visibilidad. A diferencia de ReflectionConcrete, aquí se inspeccionan los atributos asignados en la instancia (via vars(instance)), no los del diccionario de la clase.

Retorna todos los atributos de la instancia, combinando públicos, protegidos, privados y dunder.

attrs = reflection.getAttributes()
# {"public_attr": 42, "_protected_attr": "prot", "__private_attr": "priv", ...}

Retorna los atributos públicos de la instancia (sin prefijo de guión bajo).

public = reflection.getPublicAttributes()
# {"public_attr": 42}

Retorna los atributos protegidos de la instancia (prefijo _).

protected = reflection.getProtectedAttributes()
# {"_protected_attr": "prot"}

Retorna los atributos privados de la instancia (prefijo __). Los nombres se devuelven sin name mangling.

private = reflection.getPrivateAttributes()
# {"__private_attr": "priv"}

Retorna los atributos dunder de la instancia. getMagicAttributes es un alias de getDunderAttributes.

dunder = reflection.getDunderAttributes()
magic = reflection.getMagicAttributes() # Equivalente

Verifica si un atributo existe en la instancia.

reflection.hasAttribute("public_attr") # True
reflection.hasAttribute("missing") # False

Obtiene el valor de un atributo, con soporte para valor por defecto.

value = reflection.getAttribute("public_attr") # 42
value = reflection.getAttribute("missing", "default") # "default"

Establece un atributo en la instancia. Solo valores no invocables son aceptados.

reflection.setAttribute("public_attr", 100) # True

Validaciones:

  • El nombre debe ser un identificador Python válido
  • No puede ser una palabra reservada
  • El valor no puede ser un callable (lanza TypeError)

Elimina un atributo de la instancia. Lanza AttributeError si el atributo no existe.

reflection.removeAttribute("public_attr") # True

Retorna el docstring de un atributo específico, o None si no tiene. Lanza AttributeError si el atributo no existe.

doc = reflection.getAttributeDocstring("public_attr")

ReflectionInstance ofrece la misma API granular que ReflectionConcrete para inspeccionar métodos, organizada por visibilidad (público, protegido, privado), tipo (instancia, clase, estático, dunder) y naturaleza (síncrono, asíncrono).

MétodoDescripción
getMethods()Todos los métodos (instancia + clase + estáticos)
getPublicMethods()Métodos de instancia públicos
getPublicSyncMethods()Públicos síncronos
getPublicAsyncMethods()Públicos asíncronos
getProtectedMethods()Métodos de instancia protegidos (_)
getProtectedSyncMethods()Protegidos síncronos
getProtectedAsyncMethods()Protegidos asíncronos
getPrivateMethods()Métodos de instancia privados (__)
getPrivateSyncMethods()Privados síncronos
getPrivateAsyncMethods()Privados asíncronos
getPublicClassMethods()Class methods públicos
getPublicClassSyncMethods()Class methods públicos síncronos
getPublicClassAsyncMethods()Class methods públicos asíncronos
getProtectedClassMethods()Class methods protegidos
getProtectedClassSyncMethods()Class methods protegidos síncronos
getProtectedClassAsyncMethods()Class methods protegidos asíncronos
getPrivateClassMethods()Class methods privados
getPrivateClassSyncMethods()Class methods privados síncronos
getPrivateClassAsyncMethods()Class methods privados asíncronos
getPublicStaticMethods()Static methods públicos
getPublicStaticSyncMethods()Static methods públicos síncronos
getPublicStaticAsyncMethods()Static methods públicos asíncronos
getProtectedStaticMethods()Static methods protegidos
getProtectedStaticSyncMethods()Static methods protegidos síncronos
getProtectedStaticAsyncMethods()Static methods protegidos asíncronos
getPrivateStaticMethods()Static methods privados
getPrivateStaticSyncMethods()Static methods privados síncronos
getPrivateStaticAsyncMethods()Static methods privados asíncronos
getDunderMethods()Métodos dunder (__init__, __repr__, etc.)
getMagicMethods()Alias de getDunderMethods()

Todos los métodos retornan list[str] con los nombres encontrados. Los métodos privados se retornan sin name mangling.

class MyService:
def process(self) -> str:
return "done"
async def fetch(self) -> dict:
return {}
def _validate(self) -> bool:
return True
@classmethod
def create(cls) -> "MyService":
return cls()
@staticmethod
def version() -> str:
return "1.0"
reflection = ReflectionInstance(MyService())
reflection.getPublicMethods() # ["process", "fetch"]
reflection.getPublicSyncMethods() # ["process"]
reflection.getPublicAsyncMethods() # ["fetch"]
reflection.getProtectedMethods() # ["_validate"]
reflection.getPublicClassMethods() # ["create"]
reflection.getPublicStaticMethods() # ["version"]

Verifica si un método existe en la instancia (busca en todas las categorías).

reflection.hasMethod("process") # True
reflection.hasMethod("missing") # False

Agrega un nuevo método a la instancia. Lanza AttributeError si el nombre es inválido, y TypeError si el valor no es callable.

def new_method(self) -> str:
return "new"
reflection.setMethod("new_method", new_method) # True

Elimina un método de la clase de la instancia. Lanza AttributeError si el método no existe.

reflection.removeMethod("new_method")

Retorna el objeto inspect.Signature de un método específico. Lanza AttributeError si el método no existe o no es callable.

sig = reflection.getMethodSignature("process")
# (self) -> str

Retorna el docstring de un método, o None si no tiene. Lanza AttributeError si el método no existe.

doc = reflection.getMethodDocstring("process")
# "Return the value of public_attr."

Retorna los nombres de todas las propiedades definidas en la clase de la instancia.

class Config:
@property
def host(self) -> str:
"""Server hostname."""
return "localhost"
@property
def _port(self) -> int:
return 8080
reflection = ReflectionInstance(Config())
reflection.getProperties() # ["host", "_port"]
MétodoDescripción
getPublicProperties()Propiedades públicas
getProtectedProperties()Propiedades protegidas (_)
getPrivateProperties()Propiedades privadas (__, sin mangling)

Obtiene el valor de una propiedad desde la instancia. Lanza AttributeError si no existe.

value = reflection.getProperty("host") # "localhost"

Retorna la firma del getter de una propiedad. Lanza AttributeError si no existe.

sig = reflection.getPropertySignature("host")
# (self) -> str

Retorna el docstring del getter de una propiedad, o cadena vacía si no tiene. Lanza AttributeError si no existe.

doc = reflection.getPropertyDocstring("host")
# "Server hostname."

Analiza las dependencias del constructor de la clase de la instancia, identificando parámetros resueltos (con valor por defecto o tipo primitivo) y no resueltos (que requieren inyección).

analysis = reflection.constructorSignature()
# Signature(resolved=[...], unresolved=[...])

Analiza las dependencias de un método específico. Lanza AttributeError si el método no existe.

analysis = reflection.methodSignature("process")
# Signature(resolved=[...], unresolved=[...])

ReflectionInstance implementa un sistema de caché en memoria que almacena los resultados de las operaciones de introspección para evitar recálculos costosos.

La instancia soporta acceso tipo diccionario:

# Verificar existencia
"key" in reflection
# Obtener valor (None si no existe)
reflection["key"]
# Establecer valor
reflection["key"] = value
# Eliminar entrada
del reflection["key"]

Limpia todas las entradas del caché. Las siguientes llamadas a métodos recalcularán sus resultados.

reflection.clearCache()