重定向对象列表以使用 lambda 减少函数时出错
Posted
技术标签:
【中文标题】重定向对象列表以使用 lambda 减少函数时出错【英文标题】:An error when redirecting a list of objects to reduce function with lambda 【发布时间】:2019-12-30 07:02:12 【问题描述】:这是简单的代码。
class C:
def __init__(self):
self.l = [1,2,3]
a = C()
b = C()
c = C()
reduce(lambda x,y: x.l + y.l, [a,b,c])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 1, in <lambda>
AttributeError: 'list' object has no attribute 'l'
我知道还有其他几种方法。但我想看看为什么这不起作用。
输出应该与给出的相同
sum([x.l for x in [a,b,c]], [])
这是
[1, 2, 3, 1, 2, 3, 1, 2, 3]
【问题讨论】:
预期的结果是什么?x.l + y.l
生成一个列表,该列表将反馈到下一个 reduce 调用中。您的函数期望两个参数都是 C
对象。为此,您需要返回一个 C
对象。 This 代码运行,但可能无法执行您需要它执行的操作。
我期望的是sum([x.l for x in [a,b,c]], [])
那么,你的意思是这不能写成一个 lins 代码吗?
是的,它可能可以,但我只是将它作为一个函数,让我可以在其中放置打印语句。我的代码和答案的区别在于结果是一个C
对象。可能是你想要的,也可能不是。
【参考方案1】:
作为第一个参数传递给reduce的函数有2个参数,第一个是前一个reduction的结果(或者如果没有给出初始值,则为iterable中的第一项)。在您的情况下,在将前两个列表添加在一起之后,x
现在是一个列表,当传递给 lambda 以进行第二次迭代并且没有属性 l
因为它不是 C
如果您通过map 运行您的列表,您可以从所有对象中提取列表并将它们传递给reduce
reduce(lambda x, y: x + y, map(lambda z: z.l, [a,b,c]))
【讨论】:
明确答案!谢谢!【参考方案2】:正如 Iain 在他的回答中所说,在评估第一个术语后问题就会出现,因为您的类型停止匹配。
Reduce 的形式为:reduce(f(B,A)->B, [A], optional B) -> B
您提供了一个签名为f(C, C) -> [int]
的函数
reduce(lambda x,y: x.l + y.l, [a,b,c])
与f(B,A)->B
不匹配。您可以通过更改第一个参数 (1) 或返回值 (2) 以两种方式明确解决此问题
(1)f(int, C) -> int
。其中 A 是 C,B 是 [int]。
reduce(lambda x, y: x + y.l, [a, b, c], [])
(2)f(C, C) --> C
。其中 A 是 C,B 也是 C。
def add_c(c1, c2):
ret = C()
ret.l = c1.l + c2.l
return ret
reduce(add_c, [a, b, c]).l
注意.l
以提取您的列表
请注意,第二个是丑陋的,因为您的类非常愚蠢,并且没有 init。小写 L 作为变量也是不幸的。
【讨论】:
以上是关于重定向对象列表以使用 lambda 减少函数时出错的主要内容,如果未能解决你的问题,请参考以下文章
将 packaged_task 对象移动到 lambda 捕获时出错
通过 AWS Lambda 和 CloudFront 重定向 URL