Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

1Definiciones

Introspección
Es la capacidad de un programa para examinar su propia estructura y estado en tiempo de ejecución.
En Python, gracias a su naturaleza dinámica, podemos inspeccionar tipos, atributos y métodos de objetos, incluso sin conocerlos de antemano.
Reflexión
Va un paso más allá: no solo inspecciona, sino que modifica el comportamiento o la estructura de objetos, clases o módulos en tiempo de ejecución.

2Herramientas comunes de introspección y reflexión

FunciónDescripción
type(obj)Devuelve el tipo del objeto.
dir(obj)Lista atributos y métodos disponibles.
id(obj)Identificador único en memoria.
vars(obj)Diccionario de atributos de instancia.
getattr(obj, name[, default])Obtiene un atributo dinámicamente.
setattr(obj, name, value)Asigna un atributo dinámicamente.
hasattr(obj, name)Verifica si un atributo existe.
callable(obj)Indica si el objeto es invocable como función o método.
help(obj)Muestra la documentación.

3Ejemplo básico de introspección

class Persona:
    """Clase simple para ejemplo de introspección."""

    def __init__(self, nombre, edad):
        self.nombre = nombre
        self.edad = edad

    def saludar(self):
        print(f"Hola, soy {self.nombre} y tengo {self.edad} años.")


persona = Persona("Alice", 30)

3.1Inspección

print("Tipo de objeto:", type(persona))
print("Atributos de instancia:", vars(persona))
print("ID (memoria):", id(persona))
print("¿Tiene atributo 'nombre'?", hasattr(persona, "nombre"))
print("Nombre:", getattr(persona, "nombre"))
Output
Tipo de objeto: <class '__main__.Persona'>
Atributos de instancia: {'nombre': 'Alice', 'edad': 30}
ID (memoria): 140456048795600
¿Tiene atributo 'nombre'? True
Nombre: Alice

3.2Modificación controlada

setattr(persona, "edad", 31)
print("Edad actualizada:", getattr(persona, "edad"))
Output
Edad actualizada: 31

3.3Verificar invocabilidad

print("¿Es 'persona' invocable?", callable(persona))
print("¿Es 'persona.saludar' invocable?", callable(persona.saludar))
Output
¿Es 'persona' invocable? False
¿Es 'persona.saludar' invocable? True

4Ejemplo de reflexión con cautela

En Python es posible agregar atributos o métodos a un objeto existente en tiempo de ejecución.

Esto otorga flexibilidad, pero puede volver el código difícil de mantener si se abusa.

import types


class Persona:
    def __init__(self, nombre, edad):
        self.nombre = nombre
        self.edad = edad

    def saludar(self):
        print(f"Hola, soy {self.nombre} y tengo {self.edad} años.")


ana = Persona("Ana", 35)
juan = Persona("Juan", 40)

# Agregar atributos en tiempo de ejecución
ana.domicilio = "La Merced 123"
juan.telefono = "123-456-7890"


# Agregar un método personalizado solo a 'juan'
def saludar_con_telefono(self):
    print(
        f"Hola, soy {self.nombre}, tengo {self.edad} años "
        f"y mi teléfono es {self.telefono}."
    )

juan.saludar = types.MethodType(saludar_con_telefono, juan)

ana.saludar()
juan.saludar()
Output
Hola, soy Ana y tengo 35 años.
Hola, soy Juan, tengo 40 años y mi teléfono es 123-456-7890.

5Uso de help() para documentación

help() es una función incorporada en Python que proporciona información sobre objetos, funciones y módulos. Es especialmente útil para obtener documentación sobre cómo usar un objeto o qué métodos y atributos tiene.

class Persona:
    """Clase simple para ejemplo de documentación."""

    def __init__(self, nombre, edad):
        self.nombre = nombre
        self.edad = edad

    def saludar(self):
        """Método para saludar."""
        print(f"Hola, soy {self.nombre} y tengo {self.edad} años.")


# Crear instancia
alice = Persona("Alice", 30)

# Usar help()
help(alice)
Output
Help on Persona in module __main__ object:

class Persona(builtins.object)
 |  Persona(nombre, edad)
 |
 |  Clase simple para ejemplo de documentación.
 |
 |  Methods defined here:
 |
 |  __init__(self, nombre, edad)
 |      Initialize self.  See help(type(self)) for accurate signature.
 |
 |  saludar(self)
 |      Método para saludar.
 |
 |  ----------------------------------------------------------------------
 |  Data descriptors defined here:
 |
 |  __dict__
 |      dictionary for instance variables
 |
 |  __weakref__
 |      list of weak references to the object

6Uso de eval() para evaluar expresiones

La función eval() permite ejecutar expresiones Python desde una cadena de texto. Esto puede ser útil para evaluar dinámicamente código, pero debe usarse con extrema precaución debido a implicaciones de seguridad.

Por ejemplo, el siguiente código es peligroso si la variable expresion proviene de un usuario no confiable:

expresion = input("Introduce una expresión: ")

# ¡Peligroso! El usuario puede ejecutar cualquier código Python.
resultado = eval(expresion)

print("Resultado de la expresión:", resultado)
x = 10
expresion = "x * 2"

resultado = eval(expresion)

print("Resultado de la expresión:", resultado)
Output
Resultado de la expresión: 20

7Buenas Prácticas

La introspección y reflexión son herramientas poderosas pero que se deben utilizar con responsabilidad para construir código flexible y no código frágil. Algunas recomendaciones son:

8Recursos para profundizar