2009-08-03 24 views
5

ho qualcosa di simile a questo:Creare proprietà utilizzando lambda getter e setter

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) 

Posso sostituire get_name e set_name utilizzando le funzioni lambda?

Ho provato questo:

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

ma compilatore non piace la mia funzione setter.

+0

Che cosa è "dovrebbe occupare"? –

+0

Probabilmente "qualcosa". – hughdbrown

+0

Sembra che tu stia cercando di rendere le definizioni della proprietà più oscure. Qual è il punto di sostituire semplici funzioni con lambda? –

risposta

19

Il tuo problema è che il corpo di lambda deve essere un'espressione e l'assegnazione è un'affermazione (una distinzione forte e profonda in Python). Se ti ostini a perpetrare lambda s potrai incontrare molti di questi casi e imparare le soluzioni alternative (di solito c'è uno, anche se non sempre), come ad esempio, in questo caso:

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

cioè utilizzare il built-in setattr (che è una funzione e quindi accettabile nel corpo di lambda piuttosto che nell'assegnazione (che è un'affermazione e quindi inaccettabile nel corpo di lambda).

Modifica: È inoltre necessario eseguire il nome-pressare per l'attributo a doppia sottolineatura (cambiando __name a _X__name come si sta in classe X), dove il nome dell'attributo si presenta come una stringa tra virgolette, come manualmente deve essere in setattr, poiché il compilatore Pyhon esegue solo il nome di mangling in questione per identificatori appropriati, non per i letterali stringa.

+0

Ottimo! Grazie, Alex. – zinovii

+0

Ho ancora un problema qui. setattr funziona solo per "_nome" e non "__name". – zinovii

+0

Ah sì, è necessario eseguire manualmente il mangling in quanto è una stringa quotata - lasciami modificare di conseguenza! –

1

Se si estende un list, è anche possibile utilizzare __setitem__, in questo modo:

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))