gpt4 book ai didi

python - 使用静态装饰器进行动态装饰

转载 作者:太空宇宙 更新时间:2023-11-03 15:42:47 25 4
gpt4 key购买 nike

所以我想更新库中的一个类,但我无法控制该类(我无法触及原始源代码)。约束2:其他用户已经继承了这个父类,要求他们继承第三个类会有点“烦人”。所以我必须同时处理这两个约束:需要扩展父类,但不能通过继承它。

有一个解决方案一开始似乎更有意义,尽管它接近“猴子修补”。我自己重写了父类的一些方法。我写了一个小装饰器可以做到这一点。但我遇到了一些错误,这里没有给你完整的代码,而是一个例子。考虑以下类,此处名为 Old(父类),位于我无法触及的库中(无论如何,关于其源代码):

class Old(object):

def __init__(self, value):
self.value = value

def at_disp(self, other):
print "Value is", self.value, other
return self.value

这是一个简单的类、一个构造函数和一个带有参数的方法(为了进行更多测试)。到目前为止没有什么真正困难的。但是我的装饰器来扩展此类的方法:

def override_hook(typeclass, method_name):
hook = getattr(typeclass, method_name)
def wrapper(method):
def overriden_hook(*args, **kwargs):
print "Before the hook is called."
kwargs["hook"] = hook
ret = method(*args, **kwargs)
print "After the hook"
return ret
setattr(typeclass, method_name, overriden_hook)
return overriden_hook
return wrapper

@override_hook(Old, "at_disp")
def new_disp(self, other, hook):
print "In the new hook, before"
ret = hook(self, other)
print "In the new hook, after"
return ret

令人惊讶的是,这效果非常好。如果您创建一个 Old 实例,并调用其 at_disp 方法,则会调用新方法(并调用旧方法)。很像隐藏的继承。但真正的挑战是:

我们将尝试让一个类继承 Old。这就是用户所做的。我的“补丁”也应该适用于他们,而不需要他们做任何事情:

class New(Old):
def at_disp(self, other):
print "That's in New..."
return super(Old, self).at_disp(self, other)

如果您创建一个 New 对象,并尝试其 at_disp 方法...它会崩溃。 super() 在 Old 中找不到 at_disp。这很奇怪,因为 New 直接继承自 Old。我的猜测是,由于我的新替换方法未绑定(bind),因此 super() 无法正确找到它。如果您通过直接调用 Old.at_disp() 替换 super(),则一切正常。

有人知道如何解决这个问题吗?为什么会发生这种情况?

非常感谢!

最佳答案

两个问题。

首先,对 super 的调用应该是 super(New, self),而不是 super(Old, self)super 的第一个参数通常是“当前”类(即其方法调用 super 的类)。

其次,对 at_disp 方法的调用应该是 at_disp(other),而不是 at_disp(self, other)。当您使用 super 的两个参数形式时,您将获得一个绑定(bind)的 super 对象,其行为类似于实例,因此如果您调用它的方法,将自动传递 self .

所以调用应该是super(New, self).at_disp(other)。然后就可以了。

关于python - 使用静态装饰器进行动态装饰,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41995248/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com