Python:计算列表中类实例的总和
我对内置的 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 个回答
对于第一个使用场景,像下面这样的代码
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]
在大多数情况下是一样的。
你最后的例子会有平方级的复杂度。一个更简单的方法是保持一个运行总和:
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
是一个内置类型,所以你可能不想用它作为变量名(这样会覆盖掉内置的功能)。
你试过这样做吗:
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
。