Re:[Python-es]Re: [Python-es]Evolución dinámica de los objetos a diferentes clases

Chema Cortes chemacortes en wanadoo.es
Vie Ago 23 12:48:49 CEST 2002


> Eso está claro, pero ¿qué pasa si una persona se convierte en cliente?
> ¿Tengo que borrarlo de personas y crear una nueva instancia de cliente? ¿Qué
> pasa si una persona es a la vez cliente y proveedor?

Lo que estás pidiendo es una transformación de "casting". Python sí puede hacerlo, más o menos decentemente. Aquí te pongo código que te puede orientar:

# Las clases con las que trabajamos

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

class Cliente:
    def __init__(self, nombre, cod_cliente):
        self.nombre=nombre
        self.cod_cliente=cod_cliente

class Proveedor:
    def __init__(self, nombre, cod_proveedor):
        self.nombre=nombre
        self.cod_proveedor=cod_proveedor

# No he puesto que "Cliente" y "Proveedor" hereden
# de "Persona" para hacerlo más general (Cliente
# y Proveedor también podrían ser una empresa)


# Creo una persona
p=Persona("Pepe")

# Se convierte en "Cliente" (y deja de ser "Persona")

# Un método sencillo
q=Cliente(p.nombre, 1000) # Creamos un nuevo cliente
q.__dict__.update(p.__dict__) # Actualizamos a partir de 'p'
p=q

# Un método algo más seguro
import new
p=new.instance(Cliente,p.__dict__)

# Como con new.instance no se ejecuta el constructor
# hay que hacer algunos apañanos a mano
p.cod_cliente = 1000

# Ahora queremos convertirlo en "Proveedor", pero que siga
# como "Cliente"
# Creamos una nueva clase
c=new.classobj("ClienteProveedor", (Cliente, Proveedor) , {} )
p=new.instance(c,p.__dict__)
p.cod_proveedor=5

# Ahora que está un poco claro cómo hacerlo, generamos una "metaclase"
class Negocio:
    classes={} # almacén para las clases de Negocio

    def create(name, *classes): # Método estático
        k=Negocio.classes.get(name,None)
        if not k:
            k=new.classobj(name, (Negocio,)+classes, {})
            Negocio.classes[name]=k
        return k
    create=staticmethod(create)    
    
    def cast(self, klass, **args):
        if klass.__name__ not in Negocio.classes.keys():
            raise TypeError, klass
        self.__class__=klass
        self.__dict__.update(args)


# Y así se usaría
kPersona=Negocio.create("Persona",Persona)
p=kPersona("Pepe")
kCliente=Negocio.create("Cliente",Cliente)
p.cast(kCliente, cod_cliente=1000)

kClienteProveedor=Negocio.create("ClienteProveedor",Cliente,Proveedor)
p.cast(kClienteProveedor, cod_proveedor=5)

#-----------------

Seguramente se puede hacer mejor. Si aprovechas la idea, me gustaría ver cómo queda el resultado final.

Saludos,
-- 
Chema Cortes (chemacortes en wanadoo.es)
_____________________________________________________________________
Horas ilimitadas para leer y enviar correos con Tarifa Plana Wanadoo 
¡¡ desde las 3 de la tarde!!
Compruébalo en http://www.wanadoo.es/acceso-internet





Más información sobre la lista de distribución Python-es