【问题标题】:Redefine Python object method?重新定义 Python 对象方法?
【发布时间】:2022-01-12 21:16:14
【问题描述】:

假设我有一个类Foobar,我想重新定义它的一个实例的方法:

class Foobar:
    def myMethod(self):
        print('this method was not overridden')

foo = Foobar()

def foo.myMethod:
    print('this method was overridden')

问题是,这种方法会引发错误。有没有办法重新定义对象方法?

【问题讨论】:

  • 框架挑战:你为什么要这么做?类的目的是为它的所有实例定义行为。如果foo 应该表现不同,那么foo 可能不应该是Foobar 的实例。 (让myMethod 检查实例的属性以便以某种方式行事是另一回事。)

标签: python object monkeypatching redefinition


【解决方案1】:

您可以创建一个新方法并分配它

def new_method():
    print("Hello")

foo.myMethod = new_method

【讨论】:

  • 这会创建一个新的function-valued 实例属性,而不是一个方法。
【解决方案2】:

您正在尝试做的事情称为猴子补丁。

方法是非数据描述符,这意味着您在实例__dict__ 中放置的任何同名的东西都会覆盖它:

class Foobar:
    def myMethod(self):
        print('this method was not overridden')

foo = Foobar()

type(foo.myMethod) 显示method

def myMethod():
    print('this method was overridden')

foo.myMethod = myMethod

现在type(foo.myMethod) 显示function

由于您从foo.__dict__ 访问foo.myMethod(),您将无法调用描述符协议。换句话说,您将无法将self 传递给myMethod

要完全替换方法,手动调用描述符协议,并创建绑定的方法对象:

def myMethod(self):
    print('this method was overridden')

foo.myMethod = myMethod.__get__(foo)

现在type(foo.myMethod) 再次显示method。这很重要,因为如果您想对课程进行猴子补丁,您可以使用完整版本并使其开箱即用:

Foo.myMethod = myMethod

如果您尝试调用foo.myMethod,第一个版本会引发错误,而第二个版本会按预期工作。

【讨论】:

    猜你喜欢
    • 2021-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-07
    • 2021-09-11
    • 2017-07-13
    • 2015-01-28
    • 2011-09-27
    相关资源
    最近更新 更多