【发布时间】:2020-09-27 17:33:25
【问题描述】:
我需要覆盖多个库中的功能,并希望通过迭代我提前指定的列表以编程方式修改函数。
如果我像这样设置我的代码,则修补工作:
def monkey_patch(method):
def patch(*args, **kwargs):
print('Patch!')
return method(*args, **kwargs)
return patch
def func_a(text):
print(f'You called func_a with: {text}')
func_a('Hello') # You called func_a with: Hello
original = func_a
func_a = monkey_patch(func_a)
func_a('Hello again') # Patch!
# You called func_a with: Hello again
func_a = original
func_a('Hello one last time') # You called func_a with: Hello one last time
但是,尝试由列表驱动它失败了,因为分配认为我正在尝试将函数分配给容器而不是指向的函数:
patch_list = [(func_a, monkey_patch)]
unpatch_list = []
for patch in patch_list:
original = patch[0]
patch[0] = patch[1](patch[0]) # TypeError: 'tuple' object does not support item assignment
unpatch_list.append((patch[0], original)) # Store the original function so the patch can be removed later
for patch in unpatch_list:
patch[0] = patch[1] # TypeError: 'tuple' object does not support item assignment
有没有办法“取消引用”元组中的项目以允许列表方法起作用?
【问题讨论】:
-
我认为您从根本上误解了赋值的语义。请注意,您所做的并不是真正的猴子补丁。您正在装饰这些功能。要动态地执行此操作,您似乎希望在 inside 实际模块中执行此操作。所以一种方法是直接修改
globals()。 -
“解除引用”在 Python 中没有意义,Python 没有指针。
original指的是您感兴趣的实际函数对象。它已经“取消引用”。请注意,您使用的是tuple对象,它们是不可变的。但即使您使用列表对象,也不会真正做到您想要做的事情 -
谢谢@juanpa.arrivillaga! Globals() 正是我所需要的,它现在完美运行。
标签: python monkeypatching