2009-08-03 5 views
5

mam coś takiego:Tworzenie obiektów za pomocą lambda getter i 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) 

można zastąpić get_name i set_name użyciu funkcji lambda?

Próbowałem to:

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

ale kompilator nie lubi mojej funkcji seter.

+0

Co to jest "smth"? –

+0

Prawdopodobnie "coś". – hughdbrown

+0

Wygląda na to, że starasz się, aby definicje właściwości były bardziej niejasne. Jaki jest sens zastąpienia prostych funkcji lambdami? –

Odpowiedz

19

Twoim problemem jest to, że ciało lambda musi być wyrażeniem, a przydział jest stwierdzeniem (silne, głębokie rozróżnienie w Pythonie). Jeśli nalegać na popełnienie lambda s spotkasz wiele takich przypadków i nauczyć się obejść (jest zwykle jeden, choć nie zawsze), jak w tym przypadku:

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

tj użyć wbudowanego w setattr (która jest funkcją, a zatem akceptowalna w ciele lambda), a nie przypisywana (co jest stwierdzeniem, a zatem niedopuszczalnym w ciele lambda).

Edit: Należy również wykonać nazwa-maglowania dla atrybutu podwójnego podkreślenia ręcznie (zmiana __name do _X__name jak jesteś w klasie X), gdzie nazwa atrybutu jest przedstawiony jako cudzysłowie, ponieważ musi znajdować się w setattr, ponieważ kompilator Pyhon robi tylko omawianą nazwę dla odpowiednich identyfikatorów, a nie dla literałów łańcuchowych.

+0

Świetnie! Dziękuję, Alex. – zinovii

+0

Mam jeszcze jeden problem. setattr działa tylko dla "_name", a nie "__name". – zinovii

+0

Ach tak, musisz ręcznie przeprowadzić manewrowanie, ponieważ jest to ciąg cytowany - pozwól mi odpowiednio edytować! –

1

Jeśli rozszerzenie list, można również użyć __setitem__ coś takiego:

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