2009-08-03 9 views
5

tengo algo como esto:Crear inmueble con captador lambda y colocador

class X(): 
    def __init__(self): 
     self.__name = None 

    def _process_value(self, value): 
     # do something 
     pass 

    def get_name(self): 
     return self.__name 

    def set_name(self, value): 
     self.__name = self._process_value(value) 

    name = property(get_name, set_name) 

¿Puedo reemplazar get_name y set_name usando funciones lambda?

He intentado esto:

name = property(lambda self: self.__name, lambda self, value: self.__name = self.process_value(value)) 

pero compilador no le gustan mis función de colocador.

+0

¿Qué es "algo bajo"? –

+0

Probablemente 'algo'. – hughdbrown

+0

Parece que está tratando de hacer las definiciones de propiedad más oscuras. ¿Cuál es el punto de reemplazar funciones simples con lambdas? –

Respuesta

19

Su problema es que el cuerpo de lambda debe ser una expresión y la asignación es una afirmación (una distinción fuerte y profunda en Python). Si insiste en perpetrar lambda s va a coincidir muchos de estos casos y aprender las soluciones (por lo general hay uno, aunque no siempre), como por ejemplo, en este caso:

name = property(lambda self: self.__name, 
       lambda self, value: setattr(self, 
              '_X__name', 
              self.process_value(value))) 

es decir, utiliza el incorporado en setattr (que es una función y, por lo tanto, aceptable en un cuerpo lambda) en lugar de asignación (que es una afirmación y, por lo tanto, inaceptable en un cuerpo lambda).

Editar: También necesita para llevar a cabo el nombre-mangling para el atributo de doble subrayado manualmente (cambiando __name a _X__name como estás en la clase X), donde el nombre del atributo se presenta como una cadena entre comillas, ya que debe estar en setattr, ya que el compilador de Pyhon solo hace que el nombre se altere en cuestión para identificadores adecuados, no para literales de cadenas.

+0

¡Genial! Gracias, Alex. – zinovii

+0

Tengo un problema más allí. setattr funciona solo para "_name" y no "__name". – zinovii

+0

Ah sí, necesitas realizar manualmente el cambio como una cadena entre comillas - ¡déjame editar en consecuencia! –

1

Si está ampliando una list, también se puede utilizar __setitem__, así:

class Position(list): 
    def __init__(self,x=0, y=0, z=0): 
     super(Position, self).__init__((x,y,z)) 

    x = property(lambda self: self[0], 
       lambda self,value: self.__setitem__(0, value)) 
    y = property(lambda self: self[1], 
       lambda self,value: self.__setitem__(1, value)) 
    z = property(lambda self: self[2], 
       lambda self,value: self.__setitem__(2, value))