含糖和不含糖的特性

Mar*_*lez 1 python properties accessor decorator python-decorators

请不要笑。生无可恋。

这是带有 getter 和 setter 的 Python 类的规范示例(来自Wikipedia):

class Student(object):
    # Initializer
    def __init__(self, name):
        # An instance variable to hold the student's name
        self._name = name

    # Getter method
    @property
    def name(self):
        return self._name

    # Setter method
    @name.setter
    def name(self, new_name):
        self._name = new_name
Run Code Online (Sandbox Code Playgroud)

现在我没有装饰器的版本:

class Student(object):
    # Initializer
    def __init__(self, name):
        # An instance variable to hold the student's name
        self._name = name

    # Getter method
    def name(self):
        return self._name
    name=property(fget=name)

    # Setter method
    def set_name(self, new_name):
        self._name = new_name
    name = property(fset=set_name)
Run Code Online (Sandbox Code Playgroud)

...除了第二个版本不起作用。如果我们实例化 Student 类,例如Bob=Student('Bob'),Bob.name 会抛出 AttributeError:unreadable 属性。

我保证,一旦我的声望达到 10k,我就会捐出 100 分给在投票开始涌入之前弯腰指出错误的善良灵魂。

Mar*_*ers 5

您还需要命名吸气剂:

name = property(fget=name, fset=set_name)
Run Code Online (Sandbox Code Playgroud)

或者干脆

name = property(name, set_name)
Run Code Online (Sandbox Code Playgroud)

请参阅property文档

所述@修饰语法只是语法糖; 以下表格:

@decorator_expression
def function_name(...):
    ...
Run Code Online (Sandbox Code Playgroud)

执行如下:

def function_name(...):
    ...
function_name = decorator_expression(function_name)
Run Code Online (Sandbox Code Playgroud)

请注意如何将decorator_expression部件视为可调用的,并将函数作为第一个参数传入。Aproperty()在这方面没有什么不同。

在为 定义了第一个属性之后,您的类命名空间中name就有了一个对象name,即property对象。该对象有一个.setter()方法,它只返回属性,其中 setter 被传入的新函数替换。

因此,语法@name.setter导致调用.setter()现有property实例上的方法,并且该方法返回一个属性,它的 setter 被替换。

因此,您也可以这样拼写您的显式属性创建者:

name = property(name)
name = name.setter(set_name)
Run Code Online (Sandbox Code Playgroud)

您的版本只是将name属性(用 getter 定义)替换为一个仅定义 setter的属性,否则两者没有关系。