【问题标题】:Modifing the return value of reduce() expression modifies the input修改reduced()表达式的返回值修改输入
【发布时间】:2023-01-05 17:34:49
【问题描述】:

我编写了一个函数,将所有值从字典中收集到一个列表中,其中每个值都是一个列表。但是,后来我修改那个列表的时候,发现我原来的字典也被修改了!

from functools import reduce 

d = {'foo': [1,2,3]}
all_vals = reduce(lambda x, y: x + y, d.values()); all_vals
all_vals.append(4)
print(d)
# {'foo': [1, 2, 3, 4]}

如果字典有多个键/值,则不会发生这种情况:

from functools import reduce 

d = {'foo': [1,2,3], 'bar': [9]}
all_vals = reduce(lambda x, y: x + y, d.values()); all_vals
all_vals.append(4)
print(d)
# {'foo': [1, 2, 3], 'bar': [9]}

字典现在保持不变。谁能解释为什么 python 有这种行为?

【问题讨论】:

    标签: python


    【解决方案1】:

    在第一种情况下,.values() 有一个值,reduce 只返回该列表。当你用.append修改它时,你是修改同一个列表.

    在第二种情况下,函数实际运行,所以x + y产生一个新列表.

    顺便说一句,您不应该使用此算法来拉平值。当一个简单的时候,它不必要地低效(二次时间):

    vals = [v for values in d.values() for v in values]
    

    是线性时间。

    【讨论】:

      【解决方案2】:

      减少单个元素的可迭代永远不会应用减少功能,因为这需要两个元素。初始元素未修改地返回。

      >>> a = [0, 1, 2]
      >>> a is reduce(lambda x, y: x+y, [a])
      True
      

      【讨论】:

        【解决方案3】:

        因为在第一种情况下,您的 all_vals 只是 d.values()[0] 因为 reduce lambda 永远不会被调用,因为没有两个元素可以相互减少。

        在第二种情况下,您确实有两个元素组合在一起形成一个新列表,该列表不再引用字典中最初的列表。

        【讨论】:

          猜你喜欢
          • 2014-08-24
          • 2014-12-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-03-04
          • 2012-01-20
          • 2012-07-07
          • 1970-01-01
          相关资源
          最近更新 更多