Итак, во-первых, вызывать split('\n')
в каждой строке глупо; строка гарантированно содержит не более одного символа новой строки в конце и ничего после него, так что вы получите кучу ['all of line', '']
list
с. Чтобы избежать пустой строки, просто strip
перевод строки. Это не приведет к тому, что каждая строка будет заключена в list
, но, честно говоря, я не могу представить, почему вы хотите a list
из одного элемента list
s, содержащего по одной строке каждый .
Итак, я собираюсь продемонстрировать, как map
+ strip
, чтобы избавиться от перевода строки, , используя operator.methodcaller
, чтобы выполнить strip
в каждой строке:
from operator import methodcaller
def readFile(fileName):
try:
with open(fileName) as file:
return list(map(methodcaller('strip', '\n'), file))
except IOError:
print ("\n\033[0;31mIoError: could not open the file:\033[00m %s" %fileName)
К сожалению, поскольку ваш файл управляется контекстом (что хорошо, здесь неудобно), вам нужно list
если результат; map
ленив, и если вы не сделали list
ify до return
, оператор with
закроет файл, а извлечение данных из объекта map
приведет к d ie с исключением.
Чтобы обойти это, вы можете реализовать ее как тривиальную функцию генератора, поэтому контекст генератора сохраняет файл открытым до тех пор, пока генератор не будет исчерпан (или явно close
d, или сборщик мусора):
def readFile(fileName):
try:
with open(fileName) as file:
yield from map(methodcaller('strip', '\n'), file)
except IOError:
print ("\n\033[0;31mIoError: could not open the file:\033[00m %s" %fileName)
yield from
приведет к небольшому количеству накладных расходов по прямой итерации map
, но не намного, и теперь вам не нужно отбрасывать весь файл, если вы этого не хотите; вызывающая сторона может просто повторить результат и получить разделенную строку на каждой итерации, не вытягивая весь файл в память. У него есть небольшая слабость в том, что открытие файла будет выполняться лениво, поэтому вы не увидите исключения (если оно есть), пока не начнете выполнять итерации. Это можно обойти, но это не стоит проблем, если вам это действительно не нужно.
Я бы обычно рекомендовал последнюю реализацию, поскольку она обеспечивает гибкость вызывающей стороны. В любом случае, если они хотят получить list
, они просто упаковывают вызов в list
и получают результат list
(с небольшим количеством накладных расходов). Если они этого не сделают, они могут начать обработку быстрее и иметь гораздо меньшие требования к памяти.
Имейте в виду, вся эта функция довольно странная; замена IOError
s на print
s и (неявно) возврат None
враждебны для потребителей API (теперь они должны проверять возвращаемые значения и фактически не могут сказать, что пошло не так). В реальном коде я бы, вероятно, просто пропустил функцию и вставил:
with open(fileName) as file:
for line in map(methodcaller('strip', '\n'), file)):
# do stuff with line (with newline pre-stripped)
inline в вызывающей стороне; возможно определить split_by_newline = methodcaller('split', '\n')
глобально, чтобы использовать более дружественное имя. Это не , что много кода, и я не могу себе представить, что это специфическое c поведение необходимо во многих независимых частях вашего файла, и его встраивание устраняет проблемы, связанные с открытием и закрытием файла .