Python 使用MethodType将方法从一个实例动态添加到另一个实例

Python 使用MethodType将方法从一个实例动态添加到另一个实例,python,python-3.x,Python,Python 3.x,我试图用新方法装饰类实例。但是,如果装饰者自己添加了一个方法,它会给我一个错误 TypeError: myMethod() takes 1 positional argument but 2 were given 举一个简单的例子,假设我有一个不能修改的类MyElement,还有一个装饰器将一个方法从自身添加到MyElement的实例中 class MyElement(object): def __init(self): self._name = "MyElement"

我试图用新方法装饰类实例。但是,如果装饰者自己添加了一个方法,它会给我一个错误

TypeError: myMethod() takes 1 positional argument but 2 were given
举一个简单的例子,假设我有一个不能修改的类MyElement,还有一个装饰器将一个方法从自身添加到MyElement的实例中

class MyElement(object):
    def __init(self):
        self._name = "MyElement"

class Decorator(object):

    def myMethod(self):
        print(self._name)

    def decorate(self, element):
        element.myMethod = MethodType(self.myMethod, element)

if __name__ == '__main__':
    d = Decorator()
    p = MyElement()

    d.decorate(p)
    p.myMethod()
这给了我上面的错误。尽管我把装饰改成这样,但它仍然有效:

def decorate(self, element): 
    element.myMethod = MethodType(self.myMethod.__func__, element)

有人能解释一下MethodType到底在做什么吗?为什么必须使用func标志?

您正在使用
MethodType
将您的
装饰程序的
myMethod
方法绑定到另一个对象。这不起作用,因为当您使用
self.myMethod
访问它时,您已经得到了一个绑定方法。第一个绑定将
Decorator
对象作为
self
传递,第二个绑定在尝试将
MyElement
实例作为第二个参数传递时导致异常

有几种方法可以解决这个问题。目前还不清楚哪种方法最适合您,因为您的
myMethod
示例对
self
没有任何作用

一个选项是通过
Decorator
类访问
myMethod
,而不是通过
self
。这意味着它将被解除绑定(当然,直到您将其包装在
MethodType
中)。在此版本中,
myMethod
中看到的
self
值将是
MyElement
实例,而不是
Decorator
(阅读代码的人可能会感到惊讶)。在Python2中,未绑定方法有一个特殊的检查,即
self
是正确的类型,因此这不起作用

def decorate(self, element):
    element.myMethod = MethodType(Decorator.myMethod, element)
另一个选项是将使用
self.myMethod
获得的绑定方法保存为
元素
上的变量,而不尝试再次绑定它。使用这种方法,
self
仍然是decorator对象,即使该方法是通过
MyElement
对象调用的

def decorate(self, element):
    element.myMethod = self.myMethod
最后一个选项是保持
decoration
方法不变,但在
myMethod
中添加一个额外的参数。这将允许传入
Decorator
实例(作为
self
)和
MyElement
实例:

def myMethod(self, element):
    print("{} is decorated by {}".format(element, self))

谢谢你非常准确的回答,现在我理解了MethodType
element.myMethod=Decorator.myMethod
适合我。