【问题标题】:An error when redirecting a list of objects to reduce function with lambda重定向对象列表以使用 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 对象。可能是你想要的,也可能不是。

标签: python object lambda reduce functools


【解决方案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)-&gt;B, [A], optional B) -&gt; B

您提供了一个签名为f(C, C) -&gt; [int]的函数

reduce(lambda x,y: x.l + y.l, [a,b,c])

与f(B,A)-&gt;B 不匹配。您可以通过更改第一个参数 (1) 或返回值 (2) 以两种方式明确解决此问题

(1)f(int, C) -&gt; int。其中 A 是 C,B 是 [int]。

reduce(lambda x, y: x + y.l, [a, b, c], [])

(2)f(C, C) --&gt; 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 作为变量也是不幸的。

【讨论】:

    猜你喜欢
    • 2016-01-26
    • 2020-05-13
    • 1970-01-01
    • 2020-01-14
    • 2023-01-31
    • 2015-05-18
    • 1970-01-01
    • 1970-01-01
    • 2022-01-04
    相关资源
    最近更新 更多