Създайте свойства с помощта на ламбда getter и 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)

Мога ли да заменя get_name и set_name с помощта на ламбда функции?

Опитах това:

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

но компилаторът не харесва моята функция за настройка.


person tefozi    schedule 03.08.2009    source източник
comment
Изглежда, че се опитвате да направите дефинициите на свойствата по-неясни. Какъв е смисълът да се заменят прости функции с ламбда?   -  person S.Lott    schedule 04.08.2009


Отговори (2)


Вашият проблем е, че тялото на ламбда трябва да бъде израз, а присвояването е изявление (силно, дълбоко разграничение в Python). Ако настоявате да извършите lambdas, ще срещнете много такива случаи и ще научите заобиколните решения (обикновено има едно, но не винаги), като в този случай:

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

т.е. използвайте вградения setattr (което е функция и следователно е приемливо в тялото на lambda), а не присвояването (което е изявление и следователно е неприемливо в тялото на lambda).

Трябва също така да извършите ръчно манипулирането на имената за атрибута с двойно долно черта (като промените __name на _X__name, тъй като сте в клас X), където името на атрибута е представено като низ в кавички, както трябва да бъде в setattr, като Pyhon компилаторът само деформира въпросното име за подходящи идентификатори, а не за низови литерали.

person Alex Martelli    schedule 03.08.2009
comment
Имам още един проблем там. setattr работи само за _name, а не за __name. - person tefozi; 04.08.2009
comment
Ах, да, трябва ръчно да извършите манипулирането, тъй като това е низ в кавички -- позволете ми да редактирам съответно! - person Alex Martelli; 04.08.2009

Ако разширявате list, можете също да използвате __setitem__, като това:

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))
person Philipp Kewisch    schedule 08.12.2012