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

标签 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"

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 标志 si 是必要的?

最佳答案

您正在使用 MethodTypeDecoratormyMethod 方法绑定(bind)到另一个对象。这是行不通的,因为当您使用 self.myMethod 访问它时,您已经获得了一个绑定(bind)方法。第一个绑定(bind)将 Decorator 对象作为 self 传递,第二个绑定(bind)在尝试将 MyElement 实例作为第二个参数传递时引发异常。

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

一种选择是通过 Decorator 类访问 myMethod,而不是通过 self。这意味着它将被解除绑定(bind)(当然,直到您将其包装在 MethodType 中)。在此版本中,myMethod 中看到的 self 值将是 MyElement 实例,而不是 Decorator(这可能是让阅读代码的人感到惊讶)。在 Python 2 中,未绑定(bind)方法需要进行特殊检查以确保 self 的类型正确,因此这是行不通的。

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

另一种选择是将使用 self.myMethod 获得的绑定(bind)方法保存为 element 上的变量,而不尝试再次绑定(bind)它。使用这种方法,self 仍然是装饰器对象,即使该方法是通过 MyElement 对象调用的。

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

最后一个选择是保留 decorate 方法不变,但向 myMethod 添加一个额外的参数。这将允许传入 Decorator 实例(作为 self)和 MyElement 实例:

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

关于python - 使用 MethodType 将方法从一个实例动态添加到另一个实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29841424/

相关文章:

python - `numpy.diff` 和 `scipy.fftpack.diff` 在微分时给出不同的结果

python-3.x - pip 安装私有(private) Github 存储库的简单方法?

python - SSL错误-Python3

Python 类型提示 : how to tell X is a subclass for Foo?

python - 从类定义中获取类的名称

python - 在 Mac 终端上的 doctest 中运行 +NORMALIZE WHITESPACE 时出错

Python,如何实现类似 .gitignore 的行为

python - 读取 Unicode 文件 - Python3.2

python - 将字符串拆分为多个可能更改的变量

python - 如何在Python中将文本文件分割成适当数量的列?