簡體   English   中英

“從迭代中獲得”vs“返回iter(可迭代)”

[英]“yield from iterable” vs “return iter(iterable)”

在包裝(內部)迭代器時,通常必須將__iter__方法重新路由到底層的iterable。 請考慮以下示例:

class FancyNewClass(collections.Iterable):
    def __init__(self):
        self._internal_iterable = [1,2,3,4,5]

    # ...

    # variant A
    def __iter__(self):
        return iter(self._internal_iterable)

    # variant B
    def __iter__(self):
        yield from self._internal_iterable

變體A和B之間是否有任何顯着差異? Variant A返回一個迭代器對象,該對象已通過iter()從內部迭代中查詢。 變量B返回一個生成器對象,該對象返回內部可迭代的值。 出於某種原因,是其中一種還是其他的? collections.abc ,使用版本的yield from return iter()變體是我到目前為止使用的模式。

唯一顯着的區別是當從迭代中引發異常時會發生什么。 使用return iter()您的FancyNewClass將不會出現在異常回溯中,而將yield from它的yield from 雖然可能存在要隱藏包裝器的情況,但盡可能多地獲取有關回溯的信息通常是件好事。

其他差異:

  • return iter必須從全局變量中加載名稱iter - 這可能很慢(盡管不太可能顯着影響性能)並且可能會被搞亂(盡管任何覆蓋全局變量的人都應該得到它們得到的東西)。

  • 使用yield from可以在之前和之后插入其他yield表達式(盡管您可以同樣使用itertools.chain )。

  • 如前所述,表單中的yield from會丟棄任何生成器返回值(即raise StopException(value) 。您可以通過編寫而不是return (yield from iterator)來解決此問題。

這是一個測試,比較兩種方法的反匯編,並顯示異常追溯: http//ideone.com/1YVcSe

使用return iter()

  3           0 LOAD_GLOBAL              0 (iter)
              3 LOAD_FAST                0 (it)
              6 CALL_FUNCTION            1 (1 positional, 0 keyword pair)
              9 RETURN_VALUE
Traceback (most recent call last):
  File "./prog.py", line 12, in test
  File "./prog.py", line 10, in i
RuntimeError

使用return (yield from)

  5           0 LOAD_FAST                0 (it)
              3 GET_ITER
              4 LOAD_CONST               0 (None)
              7 YIELD_FROM
              8 RETURN_VALUE
Traceback (most recent call last):
  File "./prog.py", line 12, in test
  File "./prog.py", line 5, in bar
  File "./prog.py", line 10, in i
RuntimeError

暫無
暫無

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

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