Внешнее переопределение функции модуля Python - PullRequest
0 голосов
/ 02 июля 2018

Можно ли переопределить функцию внутреннего модуля без изменений в данном модуле?

Следующий пример - лучшее, что я могу себе представить. Исходную проблему смотрите в конце вопроса.

У меня есть пакет со следующей структурой:

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 is

def c_func():
    print('c.c_func')
    return 'return_c'

Я хочу изменить внутренний вызов на c_func () с внешнего main.py

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

Первоначальная проблема относится к частной функции Сципи, но я предполагаю, что ответ на мой вопрос обобщает следующую проблему:

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)

1 Ответ

0 голосов
/ 12 июля 2018

Я нашел временное решение, изменив атрибут код функции, которую нужно изменить. Следующий код работает как нужно:

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 Можете ли вы пропатчить просто вложенную функцию с замыканием, или нужно повторить всю внешнюю функцию?

...