jen*_*ena 18 python generator lookahead
我在Python中实现了一个基于生成器的扫描程序,它将字符串标记为表单的元组(标记类型,标记值):
for token in scan("a(b)"):
print token
Run Code Online (Sandbox Code Playgroud)
会打印
("literal", "a")
("l_paren", "(")
...
Run Code Online (Sandbox Code Playgroud)
下一个任务意味着解析令牌流,为此,我需要能够从当前的一个项目前面查看一个项目,而不必将指针向前移动.事实上,迭代器和生成器不能一次提供完整的项目序列,但是每个项目根据需要使得前瞻与列表相比有点棘手,因为除非__next__()被调用,否则下一个项目是未知的.
什么可以直接实现基于生成器的前瞻看起来像?目前我正在使用一种解决方法,这意味着从生成器中生成一个列表:
token_list = [token for token in scan(string)]
Run Code Online (Sandbox Code Playgroud)
然后很容易通过以下方式实现前瞻:
try:
next_token = token_list[index + 1]
except: IndexError:
next_token = None
Run Code Online (Sandbox Code Playgroud)
当然这只是工作正常.但是考虑到这一点,我的第二个问题就出现了:首先是否真的需要制造scan()发电机?
Ale*_*lli 22
那里有相当不错的答案,但我最喜欢的方法是使用itertools.tee- 给定一个迭代器,它返回两个(或者更多,如果请求)可以独立进行.它可以根据需要在内存中缓冲(即,如果迭代器彼此之间没有非常"失步",则不会太多).例如:
import itertools
import collections
class IteratorWithLookahead(collections.Iterator):
def __init__(self, it):
self.it, self.nextit = itertools.tee(iter(it))
self._advance()
def _advance(self):
self.lookahead = next(self.nextit, None)
def __next__(self):
self._advance()
return next(self.it)
Run Code Online (Sandbox Code Playgroud)
您可以使用此类包装任何迭代器,然后使用.lookahead包装器的属性来了解将来要返回的下一个项目.我想把所有真正的逻辑留给itertools.tee并提供这种薄胶! - )
Ned*_*der 14
您可以编写一个包装器来缓冲生成器中的一些项目,并提供一个lookahead()函数来查看这些缓冲的项目:
class Lookahead:
def __init__(self, iter):
self.iter = iter
self.buffer = []
def __iter__(self):
return self
def next(self):
if self.buffer:
return self.buffer.pop(0)
else:
return self.iter.next()
def lookahead(self, n):
"""Return an item n entries ahead in the iteration."""
while n >= len(self.buffer):
try:
self.buffer.append(self.iter.next())
except StopIteration:
return None
return self.buffer[n]
Run Code Online (Sandbox Code Playgroud)
它不漂亮,但这可能会做你想要的:
def paired_iter(it):
token = it.next()
for lookahead in it:
yield (token, lookahead)
token = lookahead
yield (token, None)
def scan(s):
for c in s:
yield c
for this_token, next_token in paired_iter(scan("ABCDEF")):
print "this:%s next:%s" % (this_token, next_token)
Run Code Online (Sandbox Code Playgroud)
打印:
this:A next:B
this:B next:C
this:C next:D
this:D next:E
this:E next:F
this:F next:None
Run Code Online (Sandbox Code Playgroud)