Reputation: 327
I'm trying to write a Python script that will read a series of loads input through a CSV file, and return the resulting force vector. The format of the CSV is:
x,y,z,load_in_x,load_in_y,load_in_z
u,v,w,load_in_x,load_in_y,load_in_z
...
Here is the script:
# 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))
When I run it, I keep getting the following error:
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've tried changing the looping index i
to int(i)
and it still gives me problems. If I manually add them like below there are no problems.
xSum = F[1].load[1] + F[2].load[1] + F[3].load[1]
Upvotes: 3
Views: 3570
Reputation: 403
I think a more pythonic way is iterating the list of fasteners:
for fastener in fastenerList:
xSum += fastener.load[0]
ySum += fastener.load[1]
zSum += fastener.load[2]
If you want your code to be really fast, you can load the csv data into a numpy.ndarray and let numpy do the summing (avoiding multiple for-loops in python) but you'll be fine with this approach if speed is not that important.
Upvotes: 2
Reputation: 55469
There are various improvements that can be made to your code. As jochen said, it's more Pythonic to directly iterate over lists rather than using an index. That principle can also be applied to the code that populates your list of Fastener objects.
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
However, we can use the built-in zip
function to condense the sumLin
function even further:
def sumLin(fastenerList):
loads = [fastener.load for fastener in fastenerList]
return [sum(t) for t in zip(*loads)]
Obviously, my code is untested, since you didn't supply us with any sample data...
Upvotes: 2
Reputation: 17132
fastenerList[i].load[1]
i
is a Fastener
object, not an integer. So calling fastenerList[i]
is invalid; you should be passing in an integer. Change:
for i in fastenerList: # 'i' is a 'Fastener' object
to
for i in range(len(fastenerList)): # 'i' is an integer
Upvotes: 4