避免列表理解中的副作用

Avoiding Side Effects in List Comprehension

处理字典列表并避免副作用(什么是副作用)的最 Pythonic 和最有效的方法是什么?

更具体地说:为什么以下代码会生成生成器对象,而几乎所有其他类似代码都会生成所需的输出?

print(sum(dictionary[site] for site in dictionary) for dictionary in listofdictionaries)

一些背景

我开始摆弄 **kwargs 并生成了我认为非常糟糕的代码。

def testing(**kwargs):
    mysum = 0
    for kw in kwargs:
        mysum += kwargs[kw]
    print(mysum)


listofdictionaries = [{"site1": 1, "room1": 2, "day1": 3}, {"site2": 4, "room2": 5, "day2": 6}]

for dictionary in listofdictionaries:
    testing(**dictionary)

我回顾了 Data Structures Document 包括 List Comprehension 并找到了实现相同输出的更好方法:

listofdictionaries = [{"site1": 1, "room1": 2, "day1": 3}, {"site2": 4, "room2": 5, "day2": 6}]
for dictionary in listofdictionaries:
    mysum = 0
    for value in dictionary:
        mysum += dictionary[value]
    print(mysum)

然后聪明一点,把它缩短了一点:

for dictionary in listofdictionaries:
    print(sum(dictionary[value] for value in dictionary))

我真的没有兴趣为了让它成为一个单行而将它变成一个单行,但是在阅读了 Stack Overflow 上无数关于避免 "side effects" 的列表理解帖子之后,我觉得可能有一个额外的步骤来采取这一点。也许我不明白什么是副作用。

无论如何,这些都应该导致输出:

6
15

你可以通过添加一个函数来计算一个字典的总和,并使用这样的列表推导来得到非常接近的结果:

def dict_sum(dictionary):
    mysum = 0
    for value in dictionary:
        mysum += dictionary[value]
    return mysum

print([dict_sum(dictionary) for dictionary in listofdictionaries])
>> [6, 15]

但是,你的双眼皮应该不会有任何副作用。我不知道你指的是什么帖子,但如果你不修改列表,那么你应该没问题,最后它们应该保持不变。

你的具体问题只打印由生成器表达式形成的实际生成器对象的表示,即这个-

(sum(dictionary[site] for site in dictionary) for dictionary in listofdictionaries)

有关打印生成器的更多详细信息,请参阅此答案-

对于这个例子,你最好使用列表理解,例如

print([sum(dictionary.values()) for dictionary in listofdictionaries])

您可以先拆包打印生成器,但对于此示例,它看起来可读性差且效率低-

print(*(sum(dictionary.values()) for dictionary in listofdictionaries))

副作用可能是一个非常宽泛的术语 - https://en.wikipedia.org/wiki/Side_effect_(computer_science) 但根据之前的回答,您没有使用这些方法以任何方式修改字典,因此没有副作用。