#python #function #enumerate
Вопрос:
Я пытаюсь взять два утверждения и поместить их в одну и ту же функцию. Это часть длинного запроса для импорта списка csv-файлов (всех разной длины, верхних и нижних колонтитулов и столбцов) в один лист Excel для импорта в базу данных. Я хотел бы настроить функции, которые могут быть вызваны для оптимизации процесса.
Прямо сейчас, если я запущу следующий код, он будет работать, и я смогу использовать два параметра: начальный файл и конечный файл, чтобы определить начало и конец данных для импорта.
beginning = 'eventID' ending = 'The Line Listing is wrong' beginFile = 0 endFile = 0 with open("testbooklet.csv") as myFile: for num, line in enumerate(myFile, 1): if beginning in line: beginFile = num with open("testbooklet.csv") as myFile: for num, line in enumerate(myFile, 1): if ending in line: endFile = num print(beginFile,endFile)
Однако; если я помещу это в функцию, я получу два разных сообщения об ошибке, в зависимости от того, как я пишу функцию. Для этой первой функции сообщение об ошибке выглядит следующим образом AttributeError: 'function' object has no attribute 'endFile'.
beginning = 'eventID' ending = 'The Line Listing is wrong' beginFile = 0 endFile = 0 # Define Function to find the first and last file lines def fileinfo(file_name): global beginFile global endFile for num, line in enumerate(file_name, 1): if beginning in line: fileinfo.beginFile = num # def endfileinfo(file_name): for num, line in enumerate(file_name, 1): if ending in line: fileinfo.endFile = num MyFile = open("testbooklet.csv") fileinfo(MyFile) print(fileinfo.beginFile, fileinfo.endFile)
Для этой функции код ошибки выглядит следующим образом: NameError: name 'endFile' is not defined
beginning = 'eventID' ending = 'The Line Listing is wrong' beginFile = 0 endFile = 0 def fileinfo(file_name): global beginFile for num, line in enumerate(file_name, 1): if beginning in line: beginFile = num global endFile for num, line in enumerate(file_name, 1): if ending in line: endFile = num MyFile = open("testbooklet.csv") fileinfo(MyFile) print(beginFile) print(endFile)
Это упрощенная версия данных, которые я использую для тестирования:
Комментарии:
1. Ошибка в первой функции произойдет, если не будет найдена соответствующая строка, так как вы не назначаете или значения по умолчанию
fileinfo.beginFile
fileinfo.endFile
.2. Присвоение атрибутов функции не является обычным способом возврата результатов из функции. Вы должны использовать
return
утверждение.3. Вы собираетесь исчерпать итератор файлов в первом цикле в версиях ваших функций. Почему бы не сделать то, что вам нужно, за один проход по файлу? Кроме того, зачем вообще использовать глобалы? Функции в python могут возвращать два числа в одной строке.
Ответ №1:
Не используйте глобальные переменные, которые изменяются функциями. Вместо этого позвольте функции возвращать все, что вам нужно, и получите обе информации за один раз:
def fileinfo(file): beginFile = None endFile = None for num, line in enumerate(file, 1): if beginning in line: beginFile = num if ending in line: endFile = num break # No need to continue return beginFile, endFile # return this information to caller myFile = open("testbooklet.csv") beginFile, endFile = fileinfo(myFile) print(beginFile, endFile)
Ответ №2:
Не используйте две петли. Первый читает весь файл, так что второму циклу нечего читать. Вы могли бы исправить это, file.seek(0)
чтобы вернуться к началу, но в этом случае нет необходимости-просто проверьте оба условия в одном цикле.
Вы также должны использовать параметры и возвращаемые значения, а не глобальные переменные.
def fileinfo(file, beginning, ending): beginFile = 0 endFile = 0 for num, line in enumerate(file, 1): if beginning in line: beginFile = num if ending in line: endFile = num return beginFile, endFile with open("testbooklet.csv") as MyFile: begin, end = fileinfo(MyFile)