2016-02-05 4 views
3

Я пытаюсь написать скрипт 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] 
+0

Помните, что индексы основаны на нуле, поэтому для 'Fastener' object' f' ваши 3 загрузки: 'f.load [0]', 'f.load [1]' и 'f. нагрузка [2] '. –

ответ

4
fastenerList[i].load[1] 

i является Fastener объектом, не является целым числом. Поэтому вызов fastenerList[i] недействителен; вы должны передавать целое число. Изменение:

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

в

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

Спасибо! Это сработало отлично! –

+0

Добро пожаловать @AndyPerez –

2

Я думаю, что более вещий способ итерации списка застежек:

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

Если вы хотите, чтобы ваш код будет очень быстро, вы можете загрузить данные csv в numpy.ndarray и пусть numpy суммирует (избегая нескольких циклов for-loops в python), но с этим будет хорошо, если скорость не так важна.

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

Очевидно, что мой код не тестировался, так как вы не предоставили нам с каким-либо образцом data ...

Смежные вопросы