gpt4 book ai didi

python - 猴子修补时如何调用原始方法?

转载 作者:太空狗 更新时间:2023-10-29 18:16:12 25 4
gpt4 key购买 nike

我不想更改主项目中的一个类。

class A():
def __init__(self, firstname, lastname):
self.firstname = firstname
self.lastname = lastname

def name(self):
# this method could be much more complex
return self.lastname.upper()

我正在尝试构建一个插件机制。到目前为止一切顺利,我有一个这样的扩展点:

if __name__ == '__main__':
''' The main project has an extension point that allows me to do'''
# for each class extension such as AExtended:
A.name = AExtended.name
''' After the extensions are loaded, some behaviours may be changed'''
a = A("John", "Doe")
print(a.name())

一个插件可以这样写:

class AExtended(A):
''' This is an extension I provide through a plugin mechanism
'''
def name(self):
return self.firstname + ' ' + self.lastname.upper()

这一切都很好。我现在得到“John DOE”。

我的问题是原来的 name() 方法可能相当复杂。换句话说,我不能在 AExtended 中调用 self.lastname.upper()。我想调用“super”方法,它不再存在,因为它已被覆盖。

我怎样才能改变我的代码,以达到这样的目的:

class AExtended(A):
def name(self):
# I'm looking for a way to call the base implementation that was in A.name()
return self.firstname + ' ' + parent.name()

感谢您的帮助!

编辑:对我尝试做的事情的一些解释。

  • 我想让插件修补A 的行为。我无力改变 A 的现有消费者
  • 有很多像A这样的类可以改变,我希望插件有完全的控制权和责任
  • 确实 AExtended 不必继承自 A,但这是访问 self.firstname 的简单方法。如果有帮助,我不介意采用不同的设计模式。

我有一个解决方法,但它不是很优雅并且难以概括

class AExtended(A):
def name(self):
# I'm looking for a way to call the base implementation that was in A.name()
return self.firstname + ' ' + self.parentname()
#in main
A.parentname = A.name
A.name = AExtended.name

最佳答案

这就是我们所说的“装饰器”模式。替换 name 的原始重新分配,让它调用一个函数,该函数采用原始名称。然后它返回一个新函数。

def name_decorator(method):
def decorate_name(self=None):
return stuff + method(self)
return decorate_name
A.name = name_decorator(A.name)

稍后,调用A.name 将以self 作为当前实例调用decorate_name方法 将是对其可用,它指向重新分配时的函数。

关于python - 猴子修补时如何调用原始方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8726238/

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