为什么Python属性需要具有相同名称的辅助函数?

Thi*_*ves 3 python overloading properties

在解释属性的文档中,有人说:

请务必为其他函数指定与原始属性相同的名称(在本例中为x).

即,getter,setter和deleter方法必须都具有相同的名称.

为什么?而且,Python禁止方法重载,不是吗?

编辑:为什么在Python 2.6中运行时以下代码失败?

class Widget(object):
    def __init__(self, thing):
        self.thing = thing
        print self.thing

    @property
    def thing(self):
        return self._thing

    @thing.setter
    def set_thing(self, value):
        self._thing = value


if __name__ == '__main__':
    Widget('Some nonsense here')  
Run Code Online (Sandbox Code Playgroud)

它的输出是:

 Traceback (most recent call last):   
 File "widget.py", line 16, in <module>
     Widget('Some nonsense here')     
 File "widget.py", line 3, in __init__
     self.thing = thing 
 AttributeError: can't set attribute
Run Code Online (Sandbox Code Playgroud)

当set_thing()重命名为thing()时,代码工作正常.

Ben*_*ack 5

Python确实没有使用方法重载的功能,但你是正确的,文档鼓励你以相同的方式命名getter和setter,并演示它来启动.这里发生了什么?

诀窍是了解方法装饰器如何在Python中工作.每当你看到这样的事情:

@foo
def bar():
    frob()
    quux()
Run Code Online (Sandbox Code Playgroud)

Python实际上做的是用这种方式重写它:

def bar():
    frob()
    quux()
bar = foo(bar)
Run Code Online (Sandbox Code Playgroud)

换句话说:定义一个函数bar,然后用调用foo bar函数的结果替换它.

虽然这一切都是正确的,但在涉及如何解析名称时,评估的顺序实际上与上述略有不同.你可能更容易假装实际发生的事情看起来更接近于此:

def __secret_internal_function_name__():
    frob()
    quux()
bar = foo(__secret_internal_function_name__)
Run Code Online (Sandbox Code Playgroud)

为什么这很重要?让我们看一下文档链接中的Python:

class C(object):
    def __init__(self):
        self._x = None

    @property
    def x(self):
        """I'm the 'x' property."""
        return self._x

    @x.setter
    def x(self, value):
        self._x = value

    @x.deleter
    def x(self):
        del self._x
Run Code Online (Sandbox Code Playgroud)

让我们使用我们现在知道的内容重写它,以了解Python实际上在做什么:

class C(object):
    def __init__(self):
        self._x = None

    def __secret_x_prop__(self):
        """I'm the 'x' property."""
        return self._x
    x = property(__secret_x_prop__)

    def __secret_x_setter__(self, value):
        self._x = value
    x = x.setter(__secret_x_setter__)

    def __secret_x_getter__(self):
        del self._x
    x = x.deleter(__secret_x_getter__)
Run Code Online (Sandbox Code Playgroud)

现在,我们实际上可以看到发生了什么:我们没有超载功能; 我们正在逐步建立一个property引用其他功能的对象.

值得注意的是,根据您创建属性的方式,名称不需要匹配.具体来说,如果使用该property函数显式创建属性,就像在文档中的第一个示例中所做的那样,名称可以是您想要的任何名称; 这个例子有他们叫getx,setxdelx,它工作正常.在我认为是一种安全预防措施,property.setter,property.deleter需要传递的函数具有相同的名称,但他们正在做幕后的同样的事情更明确的property例子.