我有两个函数:
-
我无法更改的库功能说
lib_func( func, param1)
即lib_func
将函数func
和一些其他参数param1
作为参数。 -
用户自定义函数
user_func
。
例如:
x = 0
y = 0
def user_func():
global x
global y
return sqrt(x*y)
现在的问题是我想将 x 作为参数传递给 user_func
,而不是全局变量,同时将 user_func
x 传递给 lib_func
.
函数只是一个可以调用的对象,因此使用 __call__
方法定义类原则上等同于定义函数。至少在你给予的背景下。
所以:
def user_func(x, y, z):
return anything_with(x, y, z)
相当于:
class user_class(object):
@staticmethod # staticmethod so that it can be called on the class
def __call__(x, y, z):
return anything_with(x, y, z)
就目前而言,这只是混淆。但是,当您创建具有预定义属性的实例并且仅将变量参数指定为call
的参数时,就会发生神奇的事情:
class user_class(object):
def __init__(self, x):
self.x = x
def __call__(self, y, z): # No x as parameter!
return do_anything_with(self.x, y, z) # use the predefined x here
但是你需要改变你称呼lib_func
的方式:
x = 0
user_class_instance = user_class(0)
result = lib_func(user_class_instance, param1)
因此,它将重复调用具有不同y
和z
的实例,但x
将保持不变
然而,大多数这样的lib_func
函数允许传递变量参数(这样将被赋予user_func
),例如scipy.optimize.curve_fit
:
curve_fit(user_func, x, y, [initial_guess_param1, param2, ...])
user_func
将由内部curve_fit
调用(您不必执行任何操作!
user_func(x, initial_guess_param1, param2, ...)
# Then curve-fit modifies initial_guess_param1, param2, ... and calls it again
user_func(x, initial_guess_param1, param2, ...)
# and again modifies these and calls again
user_func(x, initial_guess_param1, param2, ...)
# ... until it finds a solution
x
和y
是定义的,在调用curve_fit
时不会更改,但在找到最佳curve_fit
initial_guess_param1
时会更改.
你可以用另一个函数包装你的user_func()
def parameterized_func(local_x):
global x
x = local_x
return user_func()
然后将新的parameterized_func()
函数传递给您的lib_func()
。这不是很好,并且显然会更改全局x
变量。我建议调查一下,看看你是否不能改变user_func()
函数。
如果我正确理解了任务,您将需要两件事:
-
创建新函数以使用
x, y
参数包装user_func
使用 functools.partial 使用传递的参数再获取一个函数
下面是示例。
定义user_func
的模块user_module.py
:
x = 0
y = 0
def user_func():
global x
global y
print('user_func', x, y)
需要完成工作的模块main.py
:
def lib_func(func, param1):
print('lib_func', param1)
func()
# Create user_func with params:
import user_module
def new_user_func(x, y):
user_module.x = x
user_module.y = y
user_module.user_func()
# Use functools.partial to create user_func with ready params:
from functools import partial
f = partial(new_user_func, 1, 2)
lib_func(f, 'param1')
f = partial(new_user_func, 3, 4)
lib_func(f, 'param1')
此示例的输出:
lib_func param1
user_func 1 2
lib_func param1
user_func 3 4
尝试包装user_func
并为lib_func
返回一个新函数:
def wrapuserfunc(x):
user_func.x = x
return user_func
def user_func():
if hasattr(user_func, 'x'):
print user_func.x
lib_func(wrapuserfunc(1), param1) # user_func.x = 1
# get x in user_func
print user_func.x # x = 1
wrapuserfunc(x)
工作正常。函数是 Python 中的对象。