Создайте свойства, используя лямбда-геттер и сеттер

У меня есть что-то вроде этого:

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). Если вы настаиваете на совершении lambda, вы столкнетесь со многими такими случаями и узнаете обходные пути (обычно есть один, хотя и не всегда), например, в этом случае:

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