lambda y fijar argumentos y nested_scopes
Chema Cortés
py en ch3m4.org
Mar Mayo 4 11:12:44 CEST 2004
El Lunes, 3 de Mayo de 2004 21:23, Ernesto Revilla escribió:
> creo que Chema nos comentó alguna vez cómo se puede fijar argumentos
> para funciones.
No recuerdo bien qué dije, pero lo negaré en ausencia de mi abogado :-P
> Tengo la siguiente metaclase que crea getters y setters
> para los attributos especificados con _attributes para cualquier clase.
>
> class Metaclase(type):
> def __init__(self, name, bases, dic):
> type.__init__(self, name, bases, dic)
> if "_attributes" in dic:
> for attr in dic['_attributes']:
> # crear getter y hacerlo accesible como getAtributo
> f=lambda s, _a=attr: getattr(s,_a) # ???
> # crear setter y hacerlo accesible como setAtributo
> setattr(self, 'get'+attr.capitalize(), f) # hacer
> accesible como getAtributo
> f=lambda s, value, _a=attr: setattr(s,_a,value) # ???
> setattr(self, 'set'+attr.capitalize(), f)
>
> class A(object):
> __metaclass__=Metaclase
> _attributes=["nombre","apellidos"]
> # se crea getNombre/setNombre y getApellidos/setApellidos
>
>
> a=A()
> a.setNombre("Pepe")
> a.setApellidos("Molina")
>
> print a.getNombre(),a.getApellidos()
>
> En las lineas marcadas con ??? se utiliza un lambda para crear la
> función de acceso al dato. He pasado explícitamente el nombre del
> atributo como segundo argumento a lambda como en:
> f = lambda s, a_=....
> ya que si no lo hago de esta manera, aunque use los nested_scopes, el
> argumento no se evalua hasta que se evalúa el cuerpo de lambda, de
> manera que en:
> f=lambda s: getattr(s,attr) # ???
> attr no se evalúa hasta que de ejecute la función, con lo que siempre
> apuntará a 'apellidos'.
>
> ¿Eso es así, o hay otra manera de preevaluar una expresión para usarlo
> dentro de lambda?
Ya sabrás que existe entre los pytonisos una tremenda fobia a los scopes de
las funciones lambda. Lo mejor que puedes hacer es utilizar métodos de la
metaclase para definir los atributos. Mira qué te parece así el código:
class Metaclase(type):
def __init__(self, name, bases, dic):
type.__init__(self, name, bases, dic)
if "_attributes" in dic:
for attr in dic['_attributes']:
self.mkDescriptor(attr)
def mkDescriptor(self,attr):
def getAttr(s): return getattr(self,attr)
def setAttr(s,v): setattr(self,attr,v)
setattr(self,'get'+attr.capitalize(),getAttr)
setattr(self,'set'+attr.capitalize(),setAttr)
class A(object):
__metaclass__=Metaclase
_attributes=["nombre","apellidos"]
a=A()
a.setNombre("Pepe")
a.setApellidos("Molina")
print a.getNombre(),a.getApellidos()
> ¿sería poco recomendable usar una cadena de caracteres y eval para crear
> esas funciones?
Creo que esto es lo que preguntas en el siguiente mensaje.
Más información sobre la lista de distribución Python-es