python - ** lambda 函数列表理解中的 kwargs

标签 python lambda list-comprehension keyword-argument

问题:

我想创建一个 lambda functions 的列表使用**kwargs哪些在列表中迭代。

存在类似的问题( e.g.e.g. ),但它们不考虑迭代 **kwargs .

与之前一样,问题在于 kwargs 的值lambda 函数在列表中创建后会“延迟”求值,这意味着迭代期间分配的最后一个值将传递给所有 lambda 函数。 我已经验证这对于经典循环和推导式来说都是一个“问题”。

(2a)不是,其值为 argset从分配给所有 **kwargs 的理解的最后一次迭代开始。 (3a)更糟糕的是,同时具有 argset 的值和i从分配给 x 的最后一次迭代开始和**kwargs .

MWE

代码

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)更糟糕的是,具有两者的最后一个值 iargsets分配给x**kwargs适用于所有函数( 1{'baz': 'qux'} )。

最佳答案

解决方案

解决方案1:functools.partial

按照 solution linked 的建议作者:@Blckknght 在上面的评论中,functools.partial 可能是执行此操作的最干净的方法(见下文)。

解决方案 2:嵌套 lambda

正如 @jfs 在 this answer 中所建议的那样,一种解决方法是定义 lambda 的外层,以在分配内部 lambda 期间强制评估迭代对象的当前值,并使用 map 滚动外部 lambda,创建所需的列表。

非常少的代码:

改变

[lambda x: fun(x,**kwargs) for kwargs in kwargset]

至 (1)

[partial(fun, **kwargs) for kwargs in kwargset]

或 (2)

map(lambda kwargs: (lambda x: fun(x,**kwargs)), kwargset)

完整 MWE

代码

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'}"]

(2-1),(2-2),(3-1),(3-2) 说明可能的解决方法。

关于python - ** lambda 函数列表理解中的 kwargs,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51637323/

相关文章:

python - Tox 和 django_toolbar : ImportError

java - 如何在INTELLIJ中搜索包含lambda表达式的代码?

node.js - 如何在AWS Elasticache中测试Redis的性能?

python - 在集合列表中查找属于子集的集合并选择它们

python - 遍历元组列表并仅解压缩第一个元素

python - 求和多个python字典的对应元素

python - 查找与给定向量相似的所有向量的快速方法

Python 循环迭代,替换列表时间序列中的空值

python - HTTP 检索错误 Twilio

java - 使用 Lambda 时 Maven 插件构建失败