方法重载在Python中是不可能的!您能解释一下为什么Python中的Properties.setter不是方法重载的情况吗?
class newOne():
def __init__(self):
self.__x = 0
@property
def val(self):
return self.__x
@val.setter
def val(self,value):
self.__x = value
在上面的代码中,我有两个名为"val"(但参数集不同)的方法,它们的行为都不同。
你知道属性是描述符吗,这意味着什么?我不想解释这一点,而要理解其余的部分就需要一些知识。但基本上,属性有点神奇,这是一种特殊情况,这里没有实际的方法重载。类只有一个val属性。
class A:def f(): print(1); def f(): print(2); A().f() -> prints 2。第二个定义实际上覆盖了第一个定义。然而,实际中的val.setter将函数定义组成property对象,因此第一个定义实际上并不是"丢失"。然后,描述符开始发挥作用。
这不是方法重载,因为没有两个具有不同签名的方法可以调用。如果是方法重载,可以这样做:
obj = newOne()
print(obj.val())
obj.val(5)
但这不起作用,因为val是一个属性,而不是重载方法。
那那里发生了什么?为什么我们要用相同的名称定义两个方法,如果不重载它们会发生什么?
魔法发生在装饰工身上。作为前提条件,你必须知道
@deco
def func(...):
...
等于
def func(...):
...
func = deco(func)
因此,首先发生的事情是@property修饰器将getter函数转换为一个属性,该函数作为getter函数:
class newOne:
@property
def val(self):
return self.__x
print(newOne.val)
print(newOne.val.fget)
# output:
#
#
在此之后,@val.setter装饰器使用getter和setter函数创建一个新属性:
class newOne:
@property
def val(self):
return self.__x
@val.setter
def val(self, value):
self.__x = value
print(newOne.val)
print(newOne.val.fget)
print(newOne.val.fset)
# output:
#
#
#
(getter和setter函数具有相同的名称,因为它们都被定义为def val(...),但它们仍然是不同的函数。所以他们有不同的身份证。)
所以最后,您有一个带有getter和setter函数的val属性。您没有重载方法。
有关属性如何工作以及如何调用getter和setter函数的详细信息,请参阅描述符文档。
首先,@property修饰器创建一个名为val的描述符,并将其放在一边,以便在定义类后将其添加到类中。然后,@val.setter修饰了它的函数,并简单地将它的引用添加到val描述符中。
您的代码大致相当于
d = {}
def __init__(self):
self.__x = 0
d['__init__'] = __init__
def val(self):
return self.__x
d['val'] = property(val)
def val(self, value):
self.__x = value
# Not d['val'].__set__ = val, as previously stated
d['val'] = property(fget=d['val'], fset=val)
newOne = type('newOne', (object,), d)
# These are all"local" to, or part of the implementation of,
# the class statement, so they don't stick around in the current
# namespace.
del __init__, val, d # These are all"local" to or part of the imple
–1该名称并不无关紧要。
对@val.setter的调用等同于d['val'] = property(fget=d['val'], fset=val)而不是d['val'].__set__ = val。这可能有助于解释。在这里,你可以使getter和setter的名称不同,这可能使它更清楚。但是wim比ops类定义中的getter和setter必须具有相同的名称,这样最终只有一个属性包含这两个属性。
是的,我想在我回答完之后再检查一遍。看起来应该无关紧要。)
@alexhall是@val.setter真的重新定义了属性,还是这只是在这个伪python中最接近的属性?
它实际上创建了一个新的属性。有点像type(self)(...)。我真的不明白为什么它需要这样做,而不是改变现有的财产,但这就是它要做的。耸肩
实际上我只是在猜测,现在我想你可能是对的。当然,它必须归还一些东西,这样一来,val最终就不是没有了。但它可能只是添加了属性,然后再次返回相同的属性。
如果你知道为什么每次都会创建一个新的属性,那就在这里获得+450点。