Python:计算列表中类实例的总和

2 投票
4 回答
5979 浏览
提问于 2025-04-16 22:46

我对内置的 sum() 函数很熟悉,之前也用过,比如:

sum(list1[0:41])

这个函数可以用来对列表中的整数进行求和,但现在我遇到了一种情况,我需要对一个类的实例进行求和。

我有这样一个类:

class DataPoint:
    def __init__(self, low, high, freq):
        self.low = low
        self.high = high
        self.freq = freq

这些实例都是从一个 XML 文件中读取的浮点数,之后会放到我的代码中的一个列表里。

所以举个例子,我想做类似这样的事情:

sum(list[0:41].freq)

这个列表里包含了类的实例。

我还想把它放在一个循环里,这样 sum() 函数的第二个数字每次都会增加,比如:

for i in range(len(list)):
    sum(list[0:i+1].freq)

有没有人知道我该怎么解决这个问题,或者有没有其他的方法可以做到?

谢谢!

更新:

感谢大家的回复,我会尽量提供一些更具体的信息,而不是最开始那些概念性的东西:

# Import XML Parser
import xml.etree.ElementTree as ET

# Parse XML directly from the file path
tree = ET.parse('xml file')

# Create iterable item list
items = tree.findall('item')

# Create class for historic variables
class DataPoint:
    def __init__(self, low, high, freq):
        self.low = low
        self.high = high
        self.freq = freq

# Create Master Dictionary and variable list for historic variables
masterDictionary = {}

# Loop to assign variables as dictionary keys and associate their values with them
for item in items:
    thisKey = item.find('variable').text
    thisList = []
    masterDictionary[thisKey] = thisList

for item in items:
    thisKey = item.find('variable').text
    newDataPoint = DataPoint(float(item.find('low').text), float(item.find('high').text), float(item.find('freq').text))
    masterDictionary[thisKey].append(newDataPoint)

# Import random module for pseudo-random number generation
import random

diceDictionary = {}

# Dice roll for historic variables
for thisKey in masterDictionary.keys():
    randomValue = random.random()
    diceList = []
    diceList = masterDictionary[thisKey]
    for i in range(len(diceList)):
        if randomValue <= sum(l.freq for l in diceList[0:i+1]):
            diceRoll = random.uniform(diceList[i].low, diceList[i].high)
            diceDictionary[thisKey].append(diceRoll)

我基本上是在尝试创建一个骰子投掷的字典,以便将我的主字典的键与数据匹配。我的类中的 freq 实例指的是某些区间被应用的概率,这些概率是通过骰子投掷(随机数)来决定的。这就是我需要求和的原因。

也许这能帮助澄清我的意图?在求和的例子中,“i”将是某个变量的数据点数量。

一旦我在我的输出循环中得到了哪些投掷被选中的字典(这里没有显示),我会把它应用到下面的代码中,以便做出一些有意义的东西。

如果还有什么不清楚的地方,请告诉我。我会尝试一些建议,但也许有人可以把它简化到最基本的形式,考虑到我提供的信息。

谢谢!

4 个回答

0

对于第一个使用场景,像下面这样的代码

sum(dp.freq for dp in dp_list[:41])

可能是最合适的选择。

但是如果你想做累加和的话,其实可以把它们组合在一起,因为最终的总和就是最后一个总和。例如,

cumsums = []
for i, dp in enumerate(dp_list):
    if cumsums:
        cumsums.append(dp.freq + cumsums[-1])
    else:
        cumsums.append(dp.freq)

然后 cumsums[40] 就是前41个 DataPoint 的频率总和。你可能还可以进一步优化上面的代码(比如把 if/else 替换成 try/except IndexError),但最重要的是代码的正确性。

其他考虑事项

你可能想使用一种新的类风格,所以可以把下面的代码

class DataPoint:

改成

class DataPoint(object):

另外,你可以在列表切片中省略开头的0,因为 lst[:41]lst[0:41] 在大多数情况下是一样的。

1

你最后的例子会有平方级的复杂度。一个更简单的方法是保持一个运行总和:

total = 0
for x in list:
    total += x.freq  # total at this point is equal to the sum in your example
# and total at this point is the grand total

如果你不需要列表中每个项目的运行总和,只想要总的和,那么可以参考GaretJax的回答,里面使用了sum

另外,list是一个内置类型,所以你可能不想用它作为变量名(这样会覆盖掉内置的功能)。

7

你试过这样做吗:

sum(i.freq for i in items[0:41])

如果你需要计算最后“i”个元素的累积和,下面的方法是最有效的:

sums = [items[0].freq]
for i in items[1:]:
    sums.append(sums[-1] + i.freq)

正如其他人已经提到的,使用内置函数的名字作为变量名是一种不好的编程风格;我在上面的代码中把list换成了items

撰写回答