可读,可控的迭代器?

时间:2016-01-12 01:29:20

标签: python-3.x

我试图为an LL(1) parser制作一个确定性的无上下文语法。我希望能够使用的一件事,因为它可以使更多更简单,更少贪婪和更易于维护的文字记录(如数字,字符串,注释和引用)的解析是 k 前瞻标记,而不仅仅是 1 前瞻标记。

目前,我的解决方案(有效,但我感觉不是最理想)就像(但不是)以下内容:

for idx, tok in enumerate(toklist):
    if tok == "blah":
       do(stuff)
    elif tok == "notblah":
        try:
            toklist[idx + 1]
        except:
            whatever()
        else:
            something(else)

(您可以在上面的链接中看到我实际的,更大的实现。)

有时候,就像解析器找到字符串或块注释的开头一样,跳过"跳转"迭代器的当前计数器,这样迭代器中的许多索引都会被跳过。

理论上可以用(例如)idx += idx - toklist[idx+1:].index(COMMENT)完成,但实际上,每次循环重复时,idxobj都是使用toklist.next()重新初始化,覆盖对变量的任何更改。

显而易见的解决方案是while True:while i < len(toklist): ... i += 1,但这些问题存在一些明显的问题:

  • 迭代器上使用while就像列表一样真的是C样的,而且不是 Pythonic,除了它的事实之外与迭代器上的enumerate相比,可怕的不可读和不清楚。 (另外,对于有时可能需要的while True:,您必须处理list index out of range。)

  • 对于while的每个周期,有两种获取当前令牌的方法:

    • 到处使用toklist[i](丑陋,当你可以迭代时)
    • 在每个周期中将 toklist[i]分配给更短,更易读,更少错字的名称。这样做的缺点就是会占用内存,而且速度慢,效率低。

也许可以说while循环我应该使用的东西,但我认为while循环用于处理直到条件不再成立,和for循环用于在迭代上进行有限迭代和循环,而(n迭代LL)解析器应该清楚地实现后者。

是否有一种干净,Pythonic,有效的方法来控制和任意改变迭代器的当前索引?

这不是this的欺骗,因为所有这些答案都使用复杂的,不可读的while循环,这是我 想要的。

1 个答案:

答案 0 :(得分:4)

  

是否有一种干净,Pythonic,有效的方法来控制和任意改变迭代器的当前索引?

不,没有。您可以实现自己的迭代器类型;它不会以相同的速度运行(在Python中实现),但它是可行的。例如:

# Created outside for loop so you have name to call seek on
myseqiter = SequenceIterator(myseq)

for x in myseqiter:
    if test(x):
        # do stuff with x
    else:
        # Seek somehow, e.g.
        myseqiter.seek(1)  # Skips the next value

要使用它,您可以执行以下操作:

heightForHeaderInSection

添加诸如提供索引和值之类的行为作为练习。