如何在Python中并行地干净地循环两个文件

Yin*_*Zhu 10 python

我经常写代码如下:

lines = open('wordprob.txt','r').readlines()
words = open('StdWord.txt','r').readlines()
i = 0
for line in lines:
    v = [eval(s) for s in line.split()]
    if v[0] > v[1]:
        print words[i].strip(),
    i += 1
Run Code Online (Sandbox Code Playgroud)

是否可以避免使用变量i并缩短程序?

谢谢.

ste*_*eha 22

看起来你不在乎它的价值i是什么.你只是用它来配对lineswords.因此,我建议你一次读一行,同时读一个字.然后他们会匹配.

此外,当您使用时,您将.readlines()所有输入一次性读入内存.对于大输入,这将是缓慢的.对于这个简单的代码,一次只需要一行代码.返回的文件对象open()可以充当迭代器,一次返回一行.

如果可以,你应该避免使用eval().在一个简单的练习中你知道输入数据是什么,它是非常安全的,但是如果你从外部来源获取数据,那么使用eval()它可能会让你的计算机受到攻击.有关详细信息,请参阅此页面.我将编写我的示例代码,假设您正在使用eval()将文本转换为float值. float()也将处理整数字符串值:float('3')将返回3.0.

此外,输入行似乎只能有两个值.如果一行有额外的值,您的代码将不会检测到这种情况.我们可以更改代码以从拆分行中显式解包两个值,然后如果有两个以上的值,Python将引发异常.此外,代码将更好阅读.

所以这是我建议的重写这个例子:

lines = open('wordprob.txt','rt')
words = open('StdWord.txt','rt')

for line in lines:
    word = words.next().strip()  # in Python 3: word = next(words).strip()
    a, b = [float(s) for s in line.split()]
    if a > b:
        print word,  # in Python 3: print(word + ' ', end='')
Run Code Online (Sandbox Code Playgroud)

编辑:这是相同的解决方案,但使用izip().

import itertools
lines = open('wordprob.txt','rt')
words = open('StdWord.txt','rt')

# in Python 3, just use zip() instead of izip()
for line, word in itertools.izip(lines, words):
    word = word.strip()
    a, b = [float(s) for s in line.split()]
    if a > b:
        print word,  # in Python 3: print(word + ' ', end='')
Run Code Online (Sandbox Code Playgroud)

在Python 3中,内置zip()函数返回一个迭代器,因此您可以使用它而不需要import itertools.

编辑:最佳做法是使用with语句确保文件正确关闭,无论如何.在最近的Python版本中,您可以使用多个with语句,我将在我的解决方案中执行此操作.此外,我们可以像解压缩列表一样轻松解压缩生成器表达式,因此我更改了设置a, b为使用生成器表达式的行; 应该稍快一点.word除非我们要使用它,否则我们不需要剥离.将更改放在一起得到:

from itertools import izip

with open('wordprob.txt','rt') as lines, open('StdWord.txt','rt') as words:
    # in Python 3, just use zip() instead of izip()
    for line, word in izip(lines, words):
        a, b = (float(s) for s in line.split())
        if a > b:
            print word.strip(),  # in Python 3: print(word.strip() + ' ', end='')
Run Code Online (Sandbox Code Playgroud)


YOU*_*YOU 16

您可以尝试使用枚举,

http://docs.python.org/tutorial/datastructures.html#looping-techniques

lines = open('wordprob.txt','r').readlines()
words = open('StdWord.txt','r').readlines()
for i,line in enumerate(lines):
        v = [eval(s) for s in line.split()]
        if v[0] > v[1]:
                print words[i].strip()
Run Code Online (Sandbox Code Playgroud)

  • 我不喜欢这个解决方案,因为它将所有数据读入RAM.只要数据适合RAM,这是可以的,而且很简单,但我更喜欢适用于任何大小数据集的通用解决方案. (7认同)

Bil*_*nch 5

一般来说,枚举是一个很好的解决方案.在这种情况下,您可以执行以下操作:

lines = open('wordprob.txt','r').readlines()
words = open('StdWord.txt','r').readlines()
for word, line in zip(words, lines):
    v = [eval(s) for s in line.split()]
    if v[0] > v[1]:
            print word.strip(),
Run Code Online (Sandbox Code Playgroud)

  • `zip()`是一个循环使用两个东西的好方法.但是,在Python 2.x中,它将构建一个包含所有值的列表,因此这将占用大量内存.您可以使用`itertools.izip()`获得相同的效果,它返回一个一次返回一个值的迭代器.你可以`导入itertools`然后这样做:`for word,line in itertools.izip(open('wordprob.txt'),open('stdWord.txt')):` (4认同)