我读取文件时的时间90%,最终是这样的:
with open('file.txt') as f:
for line in f:
my_function(line)
这似乎是一个非常普遍的情况,所以我想到了一种较短的方式,但是这是安全的吗?我的意思是,文件会正确关闭,还是您看到此方法的其他问题?:
for line in open('file.txt'):
my_function(line)
编辑:感谢Eric,这似乎是最好的解决方案。希望我不会将其转变为讨论,但是当我们想在多个操作中使用行时,您如何看待这种方法(不仅是作为my_function的论点):
def line_generator(filename):
with open(filename) as f:
for line in f:
yield line
然后使用:
for line in line_generator('groceries.txt'):
print line
grocery_list += [line]
此功能是否在iTerate_over_file上有缺点?
如果经常需要,您总是可以定义:
def iterate_over_file(filename, func):
with open(filename) as f:
for line in f:
func(line)
def my_function(line):
print line,
您的Pythonic One-Liner现在是:
iterate_over_file('file.txt', my_function)
使用上下文管理器是最好的方法,这几乎可以阻止您的单线解决方案。如果您天真地想创建一个单线,您会得到:
with open('file.txt') as f: for line in f: my_function(line) # wrong code!!
这是无效的语法。
所以,如果您想要一个单线,您可以做
with open('file.txt') as f: [my_function(line) for line in f]
,但这是不好的做法,因为您仅对副作用创建列表理解(您不在乎my_function
的返回)。
另一种方法是
with open('file.txt') as f: collections.deque((my_function(line) for line in f), maxlen=0)
因此,没有创建列表的理解,您可以使用Itertools食谱强制迭代器的消耗(0大小的Deque:也没有分配的内存)
结论:
要达到" Pythonic/One-Liner"目标,我们牺牲了可读性。
有时最好的方法不在一行,时期。
在ERIC的方法上构建该方法,您还可以通过编写一个将with
用于open
的函数来使其更加通用,然后只需返回文件即可。但是,这是:
def with_open(filename):
with open(filename) as f:
return f # won't work!
不起作用,因为当功能返回时,文件f
已经被with
关闭。相反,您可以使其成为生成器函数,并且yield
单个行:
def with_open(filename):
with open(filename) as f:
for line in f:
yield line
或更短的,带有较新版本的Python:
def with_open(filename):
with open(filename) as f:
yield from f
并这样使用:
for line in with_open("test.txt"):
print line
或以下:
nums = [int(n) for n in with_open("test.txt")]