【问题标题】:Create properties using lambda getter and setter使用 lambda getter 和 setter 创建属性
【发布时间】:2010-11-16 12:48:34
【问题描述】:

我有这样的事情:

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 函数。

【问题讨论】:

  • 您似乎正试图使属性定义更加模糊。用 lambda 替换简单函数有什么意义?

标签: python lambda properties


【解决方案1】:

您的问题是 lambda 的主体必须是一个表达式,而赋值是一个语句(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 编译器只对合适的标识符进行名称修改,而不是字符串文字。

【讨论】:

  • 我还有一个问题。 setattr 仅适用于“_name”而不是“__name”。
  • 啊,是的,您需要手动执行修改,因为它是一个带引号的字符串——让我进行相应的编辑!
【解决方案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))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-11-21
    • 2015-04-25
    • 1970-01-01
    • 2016-05-01
    • 2019-04-30
    • 1970-01-01
    • 2018-11-08
    • 1970-01-01
    相关资源
    最近更新 更多