Metaclases, crear funciones a partir de plantillas de texto
Chema Cortés
py en ch3m4.org
Mar Mayo 4 12:11:37 CEST 2004
El Lunes, 3 de Mayo de 2004 21:54, Ernesto Revilla escribió:
> Hola de nuevo,
>
> cómo se crearían nuevas funciones a partir de plantillas de texto desde
> Metaclases? Sólo he encontrado la siguiente manera:
>
> class Metaclase2(type):
> def __init__(self, name, bases, dic):
> type.__init__(self, name, bases, dic)
> if "_attributes" in dic:
> ns={} # creo un espacio de nombre privado donde se van a
> crear las funciones
> for attr in dic['_attributes']:
> # crear getter y hacerlo accesible como getAtributo
> capAttr=attr.capitalize()
> getterName,setterName="get"+capAttr,"set"+capAttr
> exec("def %s(self): return self._%s" %
> (getterName,attr),ns,ns)
> exec("def %s(self, value): self._%s=value" %
> (setterName,attr),ns,ns)
> getter,setter=ns[getterName],ns[setterName] # recupero
> las funciones creadas
> setattr(self, getterName, getter) # lo hago disponible
> setattr(self, setterName, setter)
>
> class B(object):
> __metaclass__=Metaclase2
> _attributes=["nombre","apellidos"]
>
> b=B()
> b.setNombre("Erny")
> b.setApellidos("Revilla")
> print b.getNombre(),b.getApellidos()
>
> # hay una manera más breve de hacerlo, es decir, crearlos directamente
> en el mismo espacio de nombres? al menos, a mi no me funciona, indicando
> 'dic' como espacio de nombres.
Empleando __new__ en lugar de __init__ en la metaclase. Una vez que está
creada la clase, sus atributos son de sólo lectura. Por eso hay que modificar
el diccionario antes de la creación de la clase:
class Metaclase2(type):
def __new__(self, name, bases, dic):
if "_attributes" in dic:
for attr in dic['_attributes']:
# crear getter y hacerlo accesible como getAtributo
capAttr=attr.capitalize()
getterName,setterName="get"+capAttr,"set"+capAttr
exec("def %s(self): return self._%s" % (getterName,attr),dic)
exec("def %s(self, value): self._%s=value" %
(setterName,attr),dic)
return type.__new__(self, name, bases, dic)
class B(object):
__metaclass__=Metaclase2
_attributes=["nombre","apellidos"]
b=B()
b.setNombre("Erny")
b.setApellidos("Revilla")
print b.getNombre(),b.getApellidos()
Más información sobre la lista de distribución Python-es