Python 更改方法定义
我想更改类的方法定义。 这就是我的情况: (我正在从其他文件导入这些类) 当我尝试执行它时,我得到:Python 更改方法定义,python,inheritance,Python,Inheritance,我想更改类的方法定义。 这就是我的情况: (我正在从其他文件导入这些类) 当我尝试执行它时,我得到: my_method_a() takes exactly 1 argument (0 given) 因为它没有“自我” 请提供帮助。如果在修补方法之前运行类型(b.a.method\u a),您将看到。在补丁后运行相同的代码会产生。为了使函数作为方法正常工作,它必须是类的属性,而不是类的实例。当您手动调用从函数生成方法的魔法时,以下操作将起作用: b.a.method_a = my_method
my_method_a() takes exactly 1 argument (0 given)
因为它没有“自我”
请提供帮助。如果在修补方法之前运行
类型(b.a.method\u a)
,您将看到
。在补丁后运行相同的代码会产生
。为了使函数作为方法正常工作,它必须是类的属性,而不是类的实例。当您手动调用从函数生成方法的魔法时,以下操作将起作用:
b.a.method_a = my_method_a.__get__(b.a, A)
有关更多信息,请参阅
不同之处在于,在补丁之后调用
b.a.method\u a()
时,method\u a
是实例b.a
的属性,而不是类a
的属性。因此,永远不会调用函数的\uuuu get\uuu
方法来生成已将b.a
绑定到方法a
的第一个参数的instancemethod
对象
从一个角度来看,
b.a.方法a()
与a.a.方法a(b.a)
相同。Python是如何进行这种转换的?您需要了解描述符协议。所有函数对象都实现了\uuu get\uu
方法来返回instancemethod
对象,您可以将其视为原始函数,第一个参数绑定到相应的对象。考虑这个代码:
b = B()
b.a.method_a()
b
是否具有名为a
的属性?对我们在B.\uuuuu init\uuuu
中设置它b.a
是否有属性method\u a
?没有类型(b.a)
(即a
)是否具有属性方法\u a
?对A.method\u A.\uuuu get\uu(b.A,A)
,因为method\u A
是为实例而查找的。结果是一个实例方法对象,其第一个参数绑定到b.a
。(这就是为什么您可以考虑<代码> B.A.MaultAd())<代码>与<代码> A.方法A(B.A) > 现在考虑这个代码。
b = B()
b.a.method_a = my_method_a
b.a.method_a()
b
是否具有名为a
的属性?对我们在B.\uuuuu init\uuuu
中设置它
b.a
是否有属性method\u a
是。我们在打电话之前就把它调好了
b.a.method\u a
是实例查找,而不是类查找,因此不会调用描述符协议,也不会调用b.a.method\u a.\u____
,即使my_method\u a
与其他所有函数一样,也不会调用
b.a.method\u a
这会产生错误,因为函数需要一个参数
为什么不使用继承和方法重写:
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()
为什么这被认为是可以接受的-我希望适当的继承和方法重写会更好,并且更易于理解和维护。通过修补
b.a
,您已经破坏了继承b.a
的行为不再与类型a
的其他实例相同。我的意思是同时上这两门课。对不起,gkusner,我把你误认为OP,误解了你的问题。我主要是通过Python内部的方法查找工作原理来说明为什么这种天真的尝试不起作用,以及需要做些什么才能使它起作用。在某些情况下,这种定向修补是有用的;模拟对象进行测试就是一种情况。(例如,mock
包为您隐藏了这些细节。)我明白您的意思,并且原则上同意您的意见-但是从可维护性的角度来看,这种类型的补丁似乎是错误的-但是它非常酷-我从未真正看到过它。
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()