我想操作一个lambda函数列表。这个lambda函数列表都包含相同的函数,我想操作它,以便其中的函数有一个额外的参数
请参阅下面的示例
def base_function(*args):
for arg in args:
print arg
list_of_functions = [
lambda new_arg: base_function(new_arg,'arg_1'),
lambda new_arg: base_function(new_arg,'arg_2'),
lambda new_arg: base_function(new_arg,'arg_3')
]
是否可以将此功能列表更改为以下内容,而无需重写整个功能列表
list_of_functions = [
lambda new_arg: base_function(new_arg,'arg_1','another_arg'),
lambda new_arg: base_function(new_arg,'arg_2','another_arg'),
lambda new_arg: base_function(new_arg,'arg_3','another_arg')
]
请参阅下文,了解我正在尝试做的另一个例子。我有以下内容:
def simple_function(arg,capitalize=False):
if capitalize:
print arg.upper()
else:
print arg
list_of_functions = [lambda key_word: simple_function(key_word),lambda key_word: simple_function(key_word)]
但我想将list_of_functions更改为以下内容,而无需重写上面的list_of_functions或simple_function:
desired_list_of_functions = [lambda key_word: simple_function(key_word,capitalize=True),lambda key_word: simple_function(key_word,capitalize=True)]
答案 0 :(得分:0)
这是我如何使用部分应用程序,如@ austin-hastings所建议的那样:
# first example from the OP
def base_function(*args):
for arg in args:
print arg
list_of_functions = [
lambda new_arg: base_function(new_arg,'arg_1'),
lambda new_arg: base_function(new_arg,'arg_2'),
lambda new_arg: base_function(new_arg,'arg_3')
]
# solution:
from functools import partial
new_list_of_functions = [
partial(fn, 'another_arg') for fn in list_of_functions
]
要将参数放在最后,您可以查看@austin-hastings's solution。
当然,您可以使用部分应用程序隐藏list_of_functions。
然后,对于您的特定用例:
desired_list_of_functions = [
lambda key_word: simple_function(key_word,capitalize=True),
lambda key_word: simple_function(key_word,capitalize=True)
]
你可以这样做:
desired_list_of_functions = [
partial(fn, capitalize=True) for fn in list_of_functions
]
那是因为partial
将作为参数(fn, *args, **kwargs)
作为参数应用于函数。
好的,通过使用引用阴影,可以按如下方式解决您的问题:
def simple_function(arg,capitalize=False):
if capitalize:
print (arg.upper())
else:
print (arg)
list_of_functions = [lambda key_word: simple_function(key_word),lambda key_word: simple_function(key_word)]
# will print 'foo' twice
for fn in list_of_functions:
fn('foo')
simple_function = partial(simple_function, capitalize=True)
# will print 'FOO' twice
for fn in list_of_functions:
fn('foo')
上述hack利用lambda
中的list_of_functions
定义尚未绑定到simple_function
引用这一事实,因为lambda函数的内容尚未执行在运行时。
只有在调用lambda时才会对引用进行赋值,因此lambda中的simple_function
引用将指向新的部分实例而不是原始函数实例。
答案 1 :(得分:0)
有点脏的解决方案可能如下:
def simple_function(arg, capitalize=False):
if capitalize:
print arg.upper()
else:
print arg
#this function takes as its argument a lambda function which
#is assumed to merely call another global function defined within
#the same module
def transf(l):
#find out which function is being called from within the lambda
f = globals()[l.__code__.co_names[0]]
#return a lambda calling the same function with customized keyword argument
return lambda arg: f(arg, capitalize=True)
list_of_functions = [lambda key_word: simple_function(key_word),lambda key_word: simple_function(key_word)]
new_list_of_functions = list(map(transf, list_of_functions))
for f in list_of_functions:
f('x')
for f in new_list_of_functions:
f('x')
答案 2 :(得分:0)
这是一个子类partial
的版本,以便将预先指定的args放在后面。它从您提供的代码开始,然后替换它(主要是因为我可以确认行为):
def base_function(*args):
for arg in args:
print arg
list_of_functions = [
lambda new_arg: base_function(new_arg,'arg_1'),
lambda new_arg: base_function(new_arg,'arg_2'),
lambda new_arg: base_function(new_arg,'arg_3')
]
for f in list_of_functions:
f('x')
import functools
class partial_atend(functools.partial):
def __call__(self, *args, **kwargs):
f=self.func
args += self.args
kw = self.keywords.copy()
kw.update(kwargs)
return f(*args, **kw)
list_of_functions = [
partial_atend(base_function, 'arg_1'),
partial_atend(base_function, 'arg_2'),
partial_atend(base_function, 'arg_3'),
]
# Modify args:
list_of_functions = [ partial_atend(f.func, *(f.args+('another_arg',)), **f.keywords) for f in list_of_functions]
# Make the call:
print "Make the call(s)..."
for f in list_of_functions:
f('x')
有一件事值得注意:我不想搞砸可能有部分调用partial_atends调用......无论如何。所以我选择扩展列表推导中的参数,然后用一个新的部分对象替换一个部分对象。这将更快(如果重要的话),我认为它不太可能被任何实施细节搞砸。
修改强>
要解决capitalize=True
更新问题,您可以使用keywords
属性执行相同操作:
首先,修改base_function
以打印kwargs:
def base_function(*args, **kwargs):
for arg in args:
print arg
for k,v in kwargs.items():
print("{}={}".format(k,v))
然后,附上以下代码:
# Modify kwargs, add `capitalize=True`:
list_of_functions = [ partial_atend(f.func, *f.args, capitalize=True, **f.keywords) for f in list_of_functions]
打印新的lambdas:
print "Make the call(s)...capitalized"
for f in list_of_functions:
f('x')