外部重写python模块函数

外部重写python模块函数,python,function,overriding,python-module,monkeypatching,Python,Function,Overriding,Python Module,Monkeypatching,是否可以在不修改给定模块的情况下覆盖内部模块功能 下面的例子是我能想象到的最好的简化。对于原始问题,请看问题的结尾 我有一个具有以下结构的包: a ├── b.py ├── c.py └── __init__.py 其中b.py为 from c import c_func def b_func(): print('b.b_func') return c_func() def c_func(): print('c.c_func') return 'return

是否可以在不修改给定模块的情况下覆盖内部模块功能

下面的例子是我能想象到的最好的简化。对于原始问题,请看问题的结尾

我有一个具有以下结构的包:

a
├── b.py
├── c.py
└── __init__.py
其中b.py

from c import c_func

def b_func():
    print('b.b_func')
    return c_func()
def c_func():
    print('c.c_func')
    return 'return_c'
c.py

from c import c_func

def b_func():
    print('b.b_func')
    return c_func()
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)

我通过更改要修改的函数的属性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问题的启发

我发现,如果我改为使用
import c
在b.py中修改导入,那么这个示例就可以工作。然后调用函数c作为
返回c.c_func()
。但是,我希望在不修改包a的任何部分的情况下也这样做。为了将来的参考,请尝试提供一个更简洁的示例