将元素弹出堆栈的 pythonic 方法 (collections.deque)

pythonic way to pop elements out of stack (collections.deque)

TL;DR: 请参阅底部的代码。

我正在实施 Reverse Polish Notation calculator in Python, using the collections.deque 堆栈实施。

因为我也在处理具有多个参数的函数,所以我使用了一个分隔符,放在实际参数之前。例如,给定以下表达式作为输入:max(2, 3, 4)Shunting Yard 算法生成以下可迭代对象:['|', '2', '3', '4', 'max'].

当我遍历它时,分隔符和数字被压入堆栈;如果遇到函数,分隔符之前的所有元素都"popped"出栈并附加到列表中。

是否有更pythonic的方法来弹出堆栈末尾的元素达到特定条件? 到目前为止我的代码:

args = []
while op_stack[-1] != FUNC_ARGS_SEPARATOR:
    args.append(op_stack.pop())

你得到的很好;没有合理的方法可以使用迭代器协议完成此任务(这通常是您清理此类内容的方式)。

理论上,如果您翻转 op_stack 的顺序(因此顶部在左侧,而不是右侧),您也许可以使用 .index 找到分隔符,然后做一个批量切片和 args.extend,然后做一个批量 del 切片,但这几乎不值得麻烦(尤其是当分隔符可能相对较快地找到时)。

这是另一个使用迭代器的解决方案。我不会将其称为对您当前解决方案的改进,但它是不同的。

from collections import deque
import itertools

d = deque(["|", "2", "3", "4", "max"])

args = list(
    itertools.takewhile(
        # Check if elt is a separator.
        # Side-effect: append separator if encountered.
        lambda elt: elt != "|" or d.append(elt),
        # Pop forever.
        (d.pop() for _ in itertools.repeat(None)),
    )
)

在朋友的帮助下,我们最终将 iter 关键字与 sep 作为 sentinel:

from collections import deque

sep = "|"
op_stack = deque([sep, 2, 3, 4])

args = iter(op_stack.pop, sep)

print(list(args))

这应该是解决这个问题的最 pythonic 和 KISS 方法之一,所以我将接受这个作为答案。

感谢大家的帮助!