循环遍历类实例列表

时间:2016-02-05 07:25:48

标签: python class loops for-loop indexing

我正在尝试编写一个Python脚本,该脚本将读取通过CSV文件输入的一系列负载,并返回生成的力矢量。 CSV的格式为:

x,y,z,load_in_x,load_in_y,load_in_z
u,v,w,load_in_x,load_in_y,load_in_z
...

这是脚本:

# Fastener class containing an ID, location in space, and load vector
class Fastener(object):
    """A collection of fasteners"""
    noOfFstnrs = 0
    def __init__(self,xyz,load):
        self.xyz = xyz
        self.load = load
        Fastener.noOfFstnrs += 1
        self.fastID = Fastener.noOfFstnrs

    def __repr__(self):
        return """Fastener ID: %s
Location: %s
Load: %s""" % (self.fastID, self.xyz, self.load)


# Request the mapping CSV file from the user. The format should be:
# x,y,z,load_in_x,load_in_y,load_in_z
path = input("Fastener mapping file: ")

with open(path,"r") as inputFile:
    inputLines = inputFile.readlines()

# Create a list of Fastener objects from each line in the mapping file
F = []
for line in range(len(inputLines)):
    inputLines[line] = inputLines[line].strip('\n')
    inputLines[line] = inputLines[line].split(",")
    location = [float(i) for i in inputLines[line][:3]]
    load = [float(i) for i in inputLines[line][3:]]
    F.append(Fastener(location,load))

# Function to sum all fastener loads and return the resulting linear force
# vector
def sumLin(fastenerList):
    xSum = 0
    ySum = 0
    zSum = 0
    for i in fastenerList:
        xSum += fastenerList[i].load[1]
        ySum += fastenerList[i].load[2]
        zSum += fastenerList[i].load[3]
    linVector = [xSum, ySum, zSum]
    return linVector

# Print 
print(sumLin(F))

当我运行它时,我不断收到以下错误:

Traceback (most recent call last):
  File "bolt_group.py", line 49, in <module>
    print(sumLin(F))
  File "bolt_group.py", line 42, in sumLin
    xSum += fastenerList[i].load[1]
TypeError: list indices must be integers, not Fastener

我尝试将循环索引i更改为int(i),但它仍然给我带来了问题。如果我像下面那样手动添加它们就没有问题。

xSum = F[1].load[1] + F[2].load[1] + F[3].load[1]

3 个答案:

答案 0 :(得分:4)

fastenerList[i].load[1]

iFastener对象,不是整数。因此调用fastenerList[i]无效;你应该传递一个整数。变化:

for i in fastenerList: # 'i' is a 'Fastener' object

for i in range(len(fastenerList)): # 'i' is an integer 

答案 1 :(得分:2)

我认为更加pythonic的方式是迭代紧固件列表:

for fastener in fastenerList:
    xSum += fastener.load[0]
    ySum += fastener.load[1]
    zSum += fastener.load[2]

如果你希望你的代码非常快,你可以将csv数据加载到numpy.ndarray中并让numpy进行求和(避免在python中使用多个for循环)但是如果速度你会很好用这种方法并不重要。

答案 2 :(得分:2)

可以对您的代码进行各种改进。正如jochen所说,直接迭代列表而不是使用索引更像是Pythonic。该原则也可以应用于填充Fastener对象列表的代码。

with open(path,"r") as inputFile:
    # Create a list of Fastener objects from each line in the mapping file
    F = []
    for line in inputLines:
        data = [float(i) for i in line.strip().split(",")]
        location = data[:3]
        load = data[3:]
        F.append(Fastener(location, load))

# Function to sum all fastener loads and return the resulting linear force
# vector
def sumLin(fastenerList):
    xSum = 0
    ySum = 0
    zSum = 0
    for fastener in fastenerList:
        xSum += fastener.load[0]
        ySum += fastener.load[1]
        zSum += fastener.load[2]
    linVector = [xSum, ySum, zSum]
    return linVector

但是,我们可以使用内置的zip函数进一步压缩sumLin函数:

def sumLin(fastenerList):
    loads = [fastener.load for fastener in fastenerList]
    return [sum(t) for t in zip(*loads)]

显然,我的代码未经测试,因为您没有向我们提供任何样本数据...