一个相当有效的方法是使用functools.partial
,但正如已经指出的,partial
只允许你“冻结”最终的参数。如果您需要其他的东西,您可以使用closure轻松实现您自己的版本。
这种做法实际上是比使用partial
对象,有点更高效,当你调用它仍然叫你通过在原有的功能,所以每两个呼叫partial
结果的通话partial
以来,和Python函数/方法调用相对较慢。如果你很好奇,看看the Python source code for functools.partial
。
在这个例子中,我将A
作为函数的第二个(伪)参数,因为partial
很好地处理了它是最后一个参数的情况。
def my_partial(param):
A = param
print('Creating two_arg_func with A ==', A)
def two_arg_func(t, y):
# Do something with all the args
return 'args', t, A, y
return two_arg_func
def test(f):
for u in range(10, 50, 10):
print(f(u, u + 5))
test(my_partial(7))
输出
Creating two_arg_func with A == 7
('args', 10, 7, 15)
('args', 20, 7, 25)
('args', 30, 7, 35)
('args', 40, 7, 45)
我们并不真正需要my_partial
param
,我们可以只使用ARG传递,因为这是本地my_partial
:
def my_partial(A):
print('Creating two_arg_func with A ==', A)
def two_arg_func(t, y):
return 'args', t, A, y
return two_arg_func
从您的意见,我现在明白,你想能够改变A
。当然,您可以通过再次拨打partial
或my_partial
来完成此操作,但是如果您想修改A
,那么效果不佳。
您的意见表明您想要在全球范围内修改A
,所以您不妨使用全局。您不需要将代码修改为A
到全局上下文中,您可以将其包装在一个函数中,但当然将需要在修改A
的函数中使用global
指令。不过,您需要而不是需要指令global
,它只读取A
的值。
这是一个简短的演示。
def two_arg_func(t, y):
# Do something with the args and with A
return 'args', t, A, y
def solve(f):
for u in range(10, 40, 10):
print('SOLVER', f(u, u + 5))
def test(f):
global A
for A in range(7, 10):
print(A)
solve(f)
test(two_arg_func)
输出
7
SOLVER ('args', 10, 7, 15)
SOLVER ('args', 20, 7, 25)
SOLVER ('args', 30, 7, 35)
8
SOLVER ('args', 10, 8, 15)
SOLVER ('args', 20, 8, 25)
SOLVER ('args', 30, 8, 35)
9
SOLVER ('args', 10, 9, 15)
SOLVER ('args', 20, 9, 25)
SOLVER ('args', 30, 9, 35)
然而,以前的解决方案是有点不满意,因为你的问题的主旨是如何使用全局为此没有。所以这里有一些代码的细微变化。我们不把A
放在全局名称空间中,而是将它作为函数属性附加到two_arg_func
。我们可以这样做,因为Python函数是一个对象,并且它已经有很多属性;两个你可能熟悉的是__name__
和__doc__
。无论如何,这是新代码,它打印出与以前版本相同的输出。
def two_arg_func(t, y):
A = two_arg_func.A
# Do something with the args and with A
return 'args', t, A, y
def solve(f):
for u in range(10, 40, 10):
print('SOLVER', f(u, u + 5))
def test(f):
for A in range(7, 10):
print(A)
f.A = A
solve(f)
test(two_arg_func)
还有'functools.partial' –
有没有必要避免像鼠疫lambdas。也就是说,'def'可以做任何'lambda';你只是忘了'返回'的价值。 'functools.partial'也可以工作,尽管它不能修正前面不存在的位置参数。 – user2357112
Guido对'lambda'的主要反对意见是当人们用它来包装一个简单的表达式来传递给map(或filter)而不是直接在列表comp或gen exp中执行表达式,例如'map(lambda x :5 * x + 1,seq)'vs'(5 * x + 1 for x in seq)''。请注意,'map'version会引发'seq'中每个项目的Python函数调用的开销。当然,如果传递给'map'的可调用函数在C中实现,例如'map(int,list_of_strings)'完全没问题,那么这是无关紧要的。 –