用Python中的两个单元格从文件中读取行作为移位寄存器

用Python中的两个单元格从文件中读取行作为移位寄存器,python,Python,我需要读取一个文件的行,这样的方式将表现为两个单元的移位寄存器。 例如: with open("filename", 'r') as file: --first iteration-- present = line1 next = line2 do something --second iteration-- present = line2 next = line3 do something --third iteration-- present = lin

我需要读取一个文件的行,这样的方式将表现为两个单元的移位寄存器。 例如:

with open("filename", 'r') as file:

 --first iteration--
 present = line1
 next  = line2
    do something

 --second iteration--
 present = line2
 next = line3
   do something

 --third iteration--
 present = line3
 next = line 4
    do someting

 and so on....
可以在
打开(文件'r')
的情况下执行此操作,但不能保证在脚本可能停止时关闭文件 由于在最后一次迭代之前“做点什么”的原因

有什么优雅的方法吗?

当然可以:

with open("filename", 'r') as file:
    current_line = next(file)  # Get 1st line, advance iterator to 2nd line
    for next_line in file:
        do_something(current_line, next_line)
        current_line = next_line

蒂姆的回答很好。“爱好者”解决方案是使用
itertools.tee
使用
pairwise
配方,如图所示:

tee
是一个非常简洁的函数。它可以在任何时候使用,你想在同一个iterable上迭代多次。如果您或多或少地并行使用所有迭代器(而不是运行一个迭代直到完成,然后再执行下一个迭代等等),那么它比将整个iterable转储到
列表
或可以反复迭代的其他容器中更节省空间

基本上,您向它传递一个iterable对象,它返回许多独立的迭代器(默认情况下,两个)。原始iterable仅在处理返回迭代器之前最远的迭代器所需的范围内进行升级

下面是一个
tee
演示,它带有一个生成器,在生成一个值之前打印一条消息:

>>> import itertools
>>> def gen():
        for i in range(3):
            print("gen yielding {}".format(i))
            yield i


>>> a, b = itertools.tee(gen())
>>> next(a)
gen yielding 0
0
>>> next(a)
gen yielding 1
1
>>> next(b)
0
>>> next(b)
1
>>> next(b)
gen yielding 2
2
>>> next(b)
Traceback (most recent call last):
  File "<pyshell#245>", line 1, in <module>
    next(b)
StopIteration
>>> next(a)
2
>>> next(a)
Traceback (most recent call last):
  File "<pyshell#247>", line 1, in <module>
    next(a)
StopIteration
导入itertools >>>def gen(): 对于范围(3)中的i: 打印(格式(i)) 产量一 >>>a,b=itertools.tee(gen()) >>>下一(a) 产生0 0 >>>下一(a) 第1代 1. >>>下一(b) 0 >>>下一(b) 1. >>>下一(b) 第2代 2. >>>下一(b) 回溯(最近一次呼叫最后一次): 文件“”,第1行,在 下一(b) 停止迭代 >>>下一(a) 2. >>>下一(a) 回溯(最近一次呼叫最后一次): 文件“”,第1行,在 下一(a) 停止迭代 和都很好。要添加到解决方案池中,还可以使用deque:

from collections import deque
n = 2
with open('myfile', 'r') as infile:
    window = deque(maxlen=n)
    for line in infile:
        window.append(line)
        do_something(*window)
更一般地说,您可以创建一个生成器,该生成器从deque生成:

def sliding_window(iterable, n=2, fill_value=None, add_padding=False):
    it = iter(iterable)
    if add_padding:
        window = deque([fill_value for _ in range(n-1)], maxlen=n)
        window.append(next(it))
    else:
        window = deque([next(iterable) for _ in range(n)], maxlen=n)

    yield tuple(window)

    for item in it:
        window.append(it)
        yield tuple(window)

    if add_padding:
        for _ in range(n-1):
            window.append(fill_value)
            yield tuple(window)

请注意,如果
iterable
中的值少于
n
中的值,则上述实现将生成一个空生成器,谢谢!就在钱上!:)@Blckknght:我查看了
itertools
中的
tee
函数,但无法理解它。你能解释一下你的解决方案是如何工作的吗?@弗拉门戈:我在我的答案中添加了一个关于
tee
的解释。你不需要知道实现的细节就能理解它的功能。@Blckknght:这很好!谢谢你花时间解释!也许我不明白,但是如果程序出于某种原因退出,用
块打开一个
文件可以保证该文件将被关闭。@Joel:是的,如果
打开(…)
文件将被关闭,但我指的是它可以作为
f=open(…)打开的情况
然后需要手动关闭。这是在得到你们的帮助之前。谢谢明白了。顺便说一句,使用open(…)执行
相当于执行
try:f=open(…);最后:f.close()
。@Joel:我也喜欢窗口化的想法。所有答案都很好。我学了一些新东西。谢谢大家!@弗拉门戈:那么,别忘了对所有答案进行投票。如果答案对你更合适的话,不要犹豫,接受一个不同的答案。@Tim:好了!如果可以的话,我会接受他们所有人,因为他们都平等地给了我带回家的东西。我有件事要告诉你们——看看我刚刚发布的这个问题:用什么样的pythonic方式来模拟与外部设备的通信?RPyC?
def sliding_window(iterable, n=2, fill_value=None, add_padding=False):
    it = iter(iterable)
    if add_padding:
        window = deque([fill_value for _ in range(n-1)], maxlen=n)
        window.append(next(it))
    else:
        window = deque([next(iterable) for _ in range(n)], maxlen=n)

    yield tuple(window)

    for item in it:
        window.append(it)
        yield tuple(window)

    if add_padding:
        for _ in range(n-1):
            window.append(fill_value)
            yield tuple(window)