簡體   English   中英

如何優雅地使用Python迭代器

[英]How to use Python iterators elegantly

我試圖更多地使用迭代器來循環,因為我聽說它比索引循環更快。 我不確定的一件事是如何很好地對待序列的結束。 我能想到的方法是使用tryexcept StopIteration ,這對我來說看起來很難看。

更具體地說,假設我們被要求打印兩個排序列表ab的合並排序列表。 我會寫下面的內容

aNull = False
I = iter(a)
try:
    tmp = I.next()
except StopIteration:
    aNull = True

for x in b:
    if aNull:
        print x
    else:
        if x < tmp:
            print x
        else:
            print tmp,x
            try:
                tmp = I.next()
            except StopIteration:
                aNull = True

while not aNull:
    print tmp
    try:
        tmp = I.next()
    except StopIteration:
        aNull = True

你會如何編碼使它更整潔?

我認為更加對稱地處理ab會使它更容易閱讀。 此外,使用Python 2.6中的內置next函數使用默認值可以避免處理StopIteration的需要:

def merge(a, b):
    """Merges two iterators a and b, returning a single iterator that yields
    the elements of a and b in non-decreasing order.  a and b are assumed to each
    yield their elements in non-decreasing order."""

    done = object()
    aNext = next(a, done)
    bNext = next(b, done)

    while (aNext is not done) or (bNext is not done):
        if (bNext is done) or ((aNext is not done) and (aNext < bNext)):
            yield aNext
            aNext = next(a, done)
        else:
            yield bNext
            bNext = next(b, done)

for i in merge(iter(a), iter(b)):
    print i

以下函數概括了為任意多個迭代器工作的方法。

def merge(*iterators):
    """Merges a collection of iterators, returning a single iterator that yields
    the elements of the original iterators in non-decreasing order.  Each of
    the original iterators is assumed to yield its elements in non-decreasing
    order."""

    done = object()
    n = [next(it, done) for it in iterators]

    while any(v is not done for v in n):
        v, i = min((v, i) for (i, v) in enumerate(n) if v is not done)
        yield v
        n[i] = next(iterators[i], done)

你錯過了迭代器的全部內容。 你不要手動調用I.next() ,你只是迭代I

for tmp in I:
    print tmp

編輯

要合並兩個迭代器,請使用itertools模塊中非常方便的函數。 你想要的可能是izip

merged = []
for x, y in itertools.izip(a, b):
    if x < y:
        merged.append(x)
        merged.append(y)
    else:
        merged.append(y)
        merged.append(x)

再次編輯

正如評論中指出的那樣,這實際上不起作用,因為列表中的多個項目可能比列表b中的下一個項目小。 但是,我意識到還有另一個內置heapq.merge可以解決這個問題: heapq.merge

sorted的函數與列表和迭代器一起使用。 也許它不是你想要的,但以下代碼可行。


a.expand(b)
print sorted(iter(a))

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM