Simulación de Objetos en Python mediante Funciones y Ámbito

En programación, el uso de funciones globales con datos desacoplados puede ocundir a comportamientos inesperados. Considérese un ejemplo donde funcionse genéricas operan sobre estructuras de datos como diccionarios, sin restricciones de tipo.

Problema con funciones globales


def emitir_sonido(criatura):
    print("%s emite un sonido" % criatura["nombre"])

def consumir_alimento(criatura):
    print("Un %s [%s] está consumiendo alimento" % (criatura["especie"], criatura["nombre"]))

animal1 = {
    "nombre": "Rex",
    "especie": "canino",
    "género": "masculino"
}

objeto1 = {
    "nombre": "Silla",
    "especie": "mueble",
    "material": "madera"
}

emitir_sonido(animal1)  # Rex emite un sonido
consumir_alimento(objeto1)  # Un mueble [Silla] está consumiendo alimento - aplicación errónea

La función consumir_alimento se invoca incorrectamente con un objeto no relacionado, evidenciando la falta de encapsulamiento. Para solucionarlo, se puede emplear el ámbito léxico de funciones anidadas.

Encapsulamiento con funciones anidadas


def crear_animal(nombre, especie, género):
    def rugir(ser):
        print("%s está rugiendo" % ser["nombre"])
    
    def ingerir(ser):
        print("Un %s [%s] está ingiriendo" % (ser["especie"], ser["nombre"]))
    
    ser = {
        "nombre": nombre,
        "especie": especie,
        "género": género,
        "rugir": rugir,
        "ingerir": ingerir
    }
    return ser

criatura = crear_animal("Tigre", "felino", "masculino")
print(criatura)
criatura["ingerir"](criatura)

Aquí, las funciones rugir e ingerir se definen dentro de crear_animal, limitando su acceso. El diccionario resultante incluye estas funciones como métodos, y se retorna para uso externo.

Refinamiento con inicialización separada


def crear_animal(nombre, especie, género):
    def rugir(ser):
        print("%s está rugiendo" % ser["nombre"])
    
    def ingerir(ser):
        print("Un %s [%s] está ingiriendo" % (ser["especie"], ser["nombre"]))
    
    def inicializar_datos(nom, esp, gen):
        ser = {
            "nombre": nom,
            "especie": esp,
            "género": gen,
            "rugir": rugir,
            "ingerir": ingerir
        }
        return ser
    
    return inicializar_datos(nombre, especie, género)

criatura_nueva = crear_animal("Águila", "ave", "femenino")
criatura_nueva["rugir"](criatura_nueva)

Este diseño separa la lógica de inicialización, mejorando la claridad. La función externa crear_animal actúa como un constructor, mientras que las funciones internas son métodos atados al objeto, simulando los princcipios de la programación orientada a objetos en Python.

Etiquetas: Python Programación Orientada a Objetos closures funciones anidadas diccionarios

Publicado el 6-2 04:43