是否可以在不修改给定模块的情况下覆盖内部模块功能?
以下示例是我能想到的最佳简化。对于原始问题,请看问题的结尾。
我有一个具有以下结构的软件包:
a
├── b.py
├── c.py
└── __init__.py
b.py 所在的位置
from c import c_func
def b_func():
print('b.b_func')
return c_func()
和 c.py 是
def c_func():
print('c.c_func')
return 'return_c'
我想从外部 main.py
修改对 c_func()的内部调用import a
from a.b import b_func
print('Calling b_func without modification')
solution = b_func()
print(solution)
# Trying to modify the internal function
print('Calling b_func with modification')
old_c_func = a.c.c_func
def new_c_func(*args, **kwargs):
print('do something in new_c_func')
return('return_new_c')
a.c.c_func = new_c_func
solution = b_func()
print(solution)
先前的代码输出以下内容
Calling b_func without modification
b.b_func
c.c_func
return_c
Calling b_func with modification
b.b_func
c.c_func
return_c
但我希望
Calling b_func without modification
b.b_func
c.c_func
return_c
Calling b_func with modification
b.b_func
do something in new_c_func
return_new_c_func
最初的问题与Scipy的私有功能有关,但我认为我的问题的答案概括为以下问题:
import scipy
# Stack calls
# minimize calls scipy.optimize._minimize_trust_ncg
# See: https://github.com/scipy/scipy/blob/2526df72e5d4ca8bad6e2f4b3cbdfbc33e805865/scipy/optimize/_minimize.py#L463
# _minimize_trust_ncg calls scipy.optimize._trustregion._minimize_trust_region
# See: https://github.com/scipy/scipy/blob/2526df72e5d4ca8bad6e2f4b3cbdfbc33e805865/scipy/optimize/_trustregion_ncg.py#L39
from scipy.optimize import minimize
old_minimize_trust_region = scipy.optimize._trustregion._minimize_trust_region
def new_minimize_trust_region(*args, **kwargs):
print('new function')
return old_minimize_trust_region
scipy.optimize._trustregion._minimize_trust_region = new_minimize_trust_region
x0 = [2]
fun = lambda x: x**2 + 42
jac = lambda x: 2*x
hess = lambda x: 2
method = 'trust-ncg'
solution = minimize(fun, x0, method=method, jac=jac, hess=hess)
print(solution)
答案 0 :(得分:0)
我找到了一个临时解决方案,方法是更改要修改的功能的属性 code 。以下代码可根据需要工作:
import a.b
import a.c
print('Calling b_func without modification')
solution = a.b.b_func()
print(solution)
# Trying to modify the internal function
print('Calling b_func with modification')
def new_c_func(*args, **kwargs):
print('do something in new_c_func')
return('return new_c_func')
a.c.c_func.__code__ = new_c_func.__code__
solution = a.b.b_func()
print(solution)
我仍然缺少完整的解释,也不知道代码是否适当,但是可以按预期工作。我受到Stackoverflow问题Can you patch just a nested function with closure, or must the whole outer function be repeated?
的启发