我有以下代码片段
def send(self, queue, fd):
for line in fd:
data = line.strip()
if data:
queue.write(json.loads(data))
Run Code Online (Sandbox Code Playgroud)
这当然可以正常工作,但我有时会想知道是否有一种"更好"的方式来编写那种只用非空行的构造.
挑战在于它应该使用'fd'读取的迭代特性,并能够处理100+ MB范围内的文件.
更新 - 你急于得到这个问题的分数,你忽略了一个导入部分,即内存使用.例如表达式:
non_blank_lines = (line.strip() for line in fd if line.strip())
Run Code Online (Sandbox Code Playgroud)
是要将整个文件缓冲到内存中,更不用说执行两次strip()操作了.哪个适用于小文件,但是当你有100 + MB的数据(或偶尔100GB)时会失败.
部分挑战是以下工作,但是要阅读:
for line in ifilter(lambda l: l, imap(lambda l: l.strip(), fd)):
queue.write(json.loads(line))
Run Code Online (Sandbox Code Playgroud)
寻找魔术师!
最终更新:PEP-289对于我自己更好地理解[]和()与所涉及的迭代器之间的区别非常有用.
编写的代码没有任何问题,可读且高效。
另一种方法是将其编写为生成器理解:
def send(self, queue, fd):
non_blank_lines = (line.strip() for line in fd if line.strip())
for line in non_blank_lines:
queue.write(json.loads(data))
Run Code Online (Sandbox Code Playgroud)
如果您正在应用可以采用迭代器的函数,则此方法可能会很有用(简洁):例如 python3 print
non_blank_lines = (line.strip() for line in fd if line.strip())
print(*non_blank_lines, file='foo')
Run Code Online (Sandbox Code Playgroud)
要消除对 strip() 的多次调用,请将生成器理解链接在一起
stripped_lines = (line.strip() for line in fd)
non_blank_lines = (line for line in stripped_lines if line)
Run Code Online (Sandbox Code Playgroud)
请注意,生成器表达式不会对内存产生不利影响,如本pep中详述。
要更深入地了解这种方法和一些性能基准,请查看这组注释。
最后请注意,如果您不需要 strip() 的完整行为,则 rstrip() 将优于 strip()。