使用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_name
和 set_name
吗?
我试过这样做:
name = property(lambda self: self.__name, lambda self, value: self.__name = self.process_value(value))
但是编译器不喜欢我的设置函数。
2 个回答
3
如果你想扩展一个 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))
30
你的问题在于,lambda 的主体必须是一个表达式,而赋值是一个语句(在 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
中必须这样做,因为 Python 编译器只会对合适的标识符进行名称混淆,而不会对字符串字面量进行处理。