2009-08-03 59 views
5

创建属性我有这样的事情:使用lambda 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) 

可以用lambda函数代替我和get_nameset_name

我已经试过这样:

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

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

+0

什么是 “水木清华”? – 2009-08-04 01:18:01

+0

可能是'某事'。 – hughdbrown 2009-08-04 03:06:37

回答

19

你的问题是lambda的body必须是一个表达式并且赋值是一个语句(在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编译器只会为合适的标识符修改名称,而不是字符串文字。

1

如果要扩展一个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))