相当于解救或重做的Python?

2024-05-16 05:57:59 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在学习Python,我有一种情况,我想使用迭代器中的项。棘手的是,在某些条件下,我想“取消迭代”,也就是说,在循环之前将一个项放回迭代器的前面。

例如,假设我在树上摘苹果。我的果篮只能装10公斤才需要倒空。但我得先摘下每一个苹果,然后再称重,确定这个苹果是否会超过篮子的容量。

在Perl这样的语言中,我可以将apple放回树上,然后让循环表达式重新选择apple:

while ($apple = shift(@tree)) {
  $wt = weight($apple);
  if ($wt + weight(@basket) > 10) {
    send(@basket);
    @basket = ();
    unshift(@tree, $apple);
  } else {
    push(@basket, $element);
  }
}

或者我也可以使用redo,它在块的顶部恢复处理,而不计算循环表达式。所以同样的苹果可以在篮子清空后重新加工。

while ($apple = shift(@tree)) {
  $wt = weight($apple);
  if ($wt + weight(@basket) > 10) {
    send(@basket);
    @basket = ();
    redo;
  } else {
    push(@basket, $apple);
  }
}

对于这种问题,什么才是最有效的解决方案?


Tags: 苹果sendtreeappleifshift表达式push
3条回答

当else子句应该总是出现时,为什么要费心取消shift呢?

for apple in tree:
    if (apple.weight + basket.weight) > 10:
       send(basket)
       basket.clear()
    basket.add(apple)

不管怎样,我很确定Python没有你想要的那种行为。

I'm learning Python, and I have a situation where I want to consume items from an iterator. The tricky part is that under certain conditions, I want to "un-iterate." That is, put an item back onto the front of the iterator before I loop.

下面是一个简单的解决方案:

class MyIterator(object):   # undo-able iterator wrapper
    def __init__(self, iterable):
        super(MyIterator, self).__init__()
        self.iterator = iter(iterable)
        self.stack = []

    def __iter__(self):
        return self

    def next(self):
        if self.stack:
            return self.stack.pop()
        return self.iterator.next()  # Raises StopIteration eventually

    def undo(self, item):
        self.stack.append(item)
for i in  MyIterator(xrange(5)): print i
0
1
2
3
4
rng = MyIterator(xrange(5))
rng.next()
0
rng.next()
1
rng.undo(1)
rng.next()
1

我可以这么说。不要试图将迭代器包装在一个生成器表达式中,该表达式允许您“回溯”或类似的复杂操作,而是使用while循环,就像在Perl中一样!Iterators don't mix very nicely with mutation,任何人。

实现的简单转换(忽略@Patrick的优化):

while tree:
    apple = tree.pop(0)
    if apple.weight + basket.weight > 10:
        basket.send()
        basket.clear()
        tree.insert(0, apple) # Put it back.
    else:
        basket.append(apple)

或者,可以使用类似于peek的功能和顺序序列索引:

while tree:
    apple = tree[0] # Take a peek at it.
    if apple.weight + basket.weight > 10:
        basket.send()
        basket.clear()
    else:
        basket.append(tree.pop(0))

如果不喜欢“simple”参数,请查看上面(链接)线程中提到的collections.deque迭代器。

相关问题 更多 >