【问题标题】:Looping through a list of class instances循环遍历类实例列表
【发布时间】:2016-05-15 02:17:26
【问题描述】:

我正在尝试编写一个 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]

【问题讨论】:

  • 请记住,索引是从零开始的,因此对于 Fastener 对象 f,您的 3 个负载是 f.load[0]f.load[1]f.load[2]

标签: python class loops for-loop indexing


【解决方案1】:
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 

【讨论】:

    【解决方案2】:

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

    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)]
    

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

    【讨论】:

      【解决方案3】:

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

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-06-22
        • 1970-01-01
        • 2017-03-02
        • 1970-01-01
        • 2018-10-26
        • 2013-09-04
        • 2019-04-15
        相关资源
        最近更新 更多