我想使用**kwargs
创建一个lambda functions的列表,并在列表中进行迭代。
存在类似的问题(e.g.,e.g.),但他们不考虑在**kwargs
上进行迭代。
和以前一样,问题在于在列表中创建之后,lambda函数中kwargs
的值被“懒惰地”求值,这意味着在迭代过程中分配的最后一个值将传递给所有lambda函数。
我已经证明这是经典循环和理解的“问题”。
(2a)
并非如此,其值argset
来自于对所有**kwargs
的理解的最后一次迭代。
(3a)
更糟,将上次迭代中的argset
和i
的值都分配给x
和**kwargs
。
def strfun(x,**kwargs):
return 'x: {} | kwargs: {}'.format(x,kwargs)
argsets = [
{'foo': 'bar'},
{'baz': 'qux'},
]
# (1) expected behaviour:
print '(1) '+str([strfun(i,**argset) for i,argset in enumerate(argsets)])
# (2) unexpected behaviour:
funs = [lambda x: strfun(x,**argset) for argset in argsets]
print '(2) '+str([fun(i) for i,fun in enumerate(funs)])
# (3) unexpected behaviour:
funs = [lambda : strfun(i,**argset) for i,argset in enumerate(argsets)]
print '(3) '+str([fun() for fun in funs])
(1) ["x: 0 | kwargs: {'foo': 'bar'}", "x: 1 | kwargs: {'baz': 'qux'}"]
(2) ["x: 0 | kwargs: {'baz': 'qux'}", "x: 1 | kwargs: {'baz': 'qux'}"]
(3) ["x: 1 | kwargs: {'baz': 'qux'}", "x: 1 | kwargs: {'baz': 'qux'}"]
(1)
是“正确”。
(2)
不是所有功能(argsets
)的最后一个值**kwargs
分配给{'baz': 'qux'}
。
(3)
更糟,所有功能(i
的{{1}}和argsets
的最后一个值都分配给x
和**kwargs
和1
)。
答案 0 :(得分:1)
{'baz': 'qux'}
正如@Blckknght的solution linked在上面的评论中所建议的那样,functools.partial
可能是最干净的方法(见下文)。
functools.partial
正如@jfs在this answer中所建议的,一种解决方法是定义lambda的外层,以在分配内部lambda期间强制评估迭代对象的当前值,并使用lambda
,创建所需的列表。
更改
map
至(1)
[lambda x: fun(x,**kwargs) for kwargs in kwargset]
或(2)
[partial(fun, **kwargs) for kwargs in kwargset]
map(lambda kwargs: (lambda x: fun(x,**kwargs)), kwargset)
from functools import partial
def strfun(x,**kwargs):
return 'x: {} | kwargs: {}'.format(x,kwargs)
argsets = [
{'foo': 'bar'},
{'baz': 'qux'},
]
# (1) always expected behaviour:
print '(1) '+str([strfun(i,**argset) for i,argset in enumerate(argsets)])
# (2)
# unexpected behaviour:
funs = [lambda x: strfun(x,**argset) for argset in argsets]
print '(2-x) '+str([fun(i) for i,fun in enumerate(funs)])
# expected behaviour
funs = map(lambda argset: (lambda x: strfun(x,**argset)), argsets)
print '(2-1) '+str([fun(i) for i,fun in enumerate(funs)])
# expected behaviour
funs = [partial(strfun, **argset) for argset in argsets]
print '(2-2) '+str([fun(i) for i,fun in enumerate(funs)])
# (3)
# unexpected behaviour:
funs = [lambda : strfun(i,**argset) for i,argset in enumerate(argsets)]
print '(3-x) '+str([fun() for fun in funs])
# expected behaviour
funs = map(lambda (i,argset): (lambda : strfun(i,**argset)), enumerate(argsets))
print '(2-1) '+str([fun() for fun in funs])
# expected behaviour
funs = [partial(strfun, i, **argset) for i,argset in enumerate(argsets)]
print '(2-2) '+str([fun() for fun in funs])
(1) ["x: 0 | kwargs: {'foo': 'bar'}", "x: 1 | kwargs: {'baz': 'qux'}"]
(2-x) ["x: 0 | kwargs: {'baz': 'qux'}", "x: 1 | kwargs: {'baz': 'qux'}"]
(2-1) ["x: 0 | kwargs: {'foo': 'bar'}", "x: 1 | kwargs: {'baz': 'qux'}"]
(2-2) ["x: 0 | kwargs: {'foo': 'bar'}", "x: 1 | kwargs: {'baz': 'qux'}"]
(3-x) ["x: 1 | kwargs: {'baz': 'qux'}", "x: 1 | kwargs: {'baz': 'qux'}"]
(2-1) ["x: 0 | kwargs: {'foo': 'bar'}", "x: 1 | kwargs: {'baz': 'qux'}"]
(2-2) ["x: 0 | kwargs: {'foo': 'bar'}", "x: 1 | kwargs: {'baz': 'qux'}"]
说明了可能的解决方法。