使用lambda getter和setter创建属性

时间:2009-08-03 22:39:33

标签: python lambda properties

我有这样的事情:

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)

我可以使用lambda函数替换get_nameset_name吗?

我试过这个:

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

但编译器不喜欢我的setter函数。

2 个答案:

答案 0 :(得分:20)

你的问题是lambda的主体必须是一个表达式,赋值是一个声明(Python中一个强大而深刻的区别)。如果你坚持执行lambda s,你会遇到许多这样的案例,并学习解决方法(通常有一个,但并非总是如此),例如,在这种情况下:

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编译器仅针对合适的标识符执行名称修改,而不是字符串文字。

答案 1 :(得分:2)

如果您要延长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))