我想更改类的方法定义。 这是我的情况:
(我从其他文件导入这些类)
class A(object):
def __init__(self, str):
self.str = str
def method_a(self):
print self.str
class B(object):
def __init__(self, str):
self.a = A(str)
def method_b(self):
self.a.method_a()
#######################################
from module import A, B
def main():
b = B('hello')
def my_method_a(self):
print self.str + 'other definition'
b.a.method_a = my_method_a
b.method_b()
if __name__ == '__main__':
main()
当我尝试执行它时,我得到:
my_method_a() takes exactly 1 argument (0 given)
因为它没有“自我”。
请帮助。
答案 0 :(得分:2)
如果您在修补方法之前运行type(b.a.method_a)
,则会看到<type 'instancemethod'>
。在修补程序生成<type 'function'>
之后运行相同的代码。为了使函数作为方法正常工作,它必须是类的属性,而不是类的实例。以下方法可行,因为您手动调用从函数生成方法的魔法:
b.a.method_a = my_method_a.__get__(b.a, A)
有关详细信息,请参阅https://wiki.python.org/moin/FromFunctionToMethod。
不同之处在于,在修补程序后调用b.a.method_a()
时,method_a
是实例 b.a
的属性,而不是类的属性 A
。因此,永远不会调用函数的__get__
方法来生成instancemethod
对象,该对象已经b.a
绑定到method_a
的第一个参数。
从一个角度来看,b.a.method_a()
与A.method_a(b.a)
相同。 Python如何实现这种转变?您需要了解描述符协议。所有函数对象都实现__get__
方法以返回instancemethod
对象,您可以将其视为原始函数,并将第一个参数绑定到相应的对象。请考虑以下代码:
b = B()
b.a.method_a()
b
是否有名为a
的属性?是;我们在B.__init__
。b.a
是否有method_a
属性?否。type(b.a)
(即A
)是否有属性method_a
?是。A.method_a.__get__(b.a, A)
,因为查找了method_a
个实例。结果是一个实例方法对象,其第一个参数绑定到b.a
。 (这就是为什么你可以认为b.a.method_a()
与A.method_a(b.a)
相同。)现在考虑一下这段代码。
b = B()
b.a.method_a = my_method_a
b.a.method_a()
b
是否有名为a
的属性?是;我们在B.__init__
。b.a
是否有method_a
属性? 是即可。我们在尝试调用它之前设置它。b.a.method_a
是实例查找而不是类查找,因此即使b.a.method_a.__get__
具有my_method_a
函数,也不会调用描述符协议并且不会调用__get__
就像其他所有功能一样。使用零参数调用b.a.method_a
。
这会产生错误,因为函数需要一个参数。
答案 1 :(得分:0)
为什么不直接使用继承和方法覆盖:
from module import A, B
class myA(A):
def method_a(self):
print self.str + ' other definition'
class myB(B):
def __init__(self, str):
self.a = myA(str)
def main():
b = myB('hello')
b.method_b()
if __name__ == '__main__':
main()