簡體   English   中英

根據 class 理解 __iter__() 方法

[英]Understanding the __iter__() method in terms of a class

我目前正在嘗試了解有關 for 循環和生成器的更多信息,並且遇到了這段代碼:

class OdeStore:
    def __init__(self,data):
        self.data=data #list of form [[t0,u0],[t1,u1]...]
    def __iter__(self):
        for t,u in self.data: #specify the data iterated over
            yield u #how it is yielded
        
store=OdeStore([[0,1],[0.1,1.1],[0.2,1.3]])
for u in store:
   print(u)

如果我的理解是正確的,我們可以在__iter__()來定義當涉及 class 的實例時 for 循環將如何作用。 在這種情況下,我們 state ,一旦我們遍歷 OdeStore class 的實例,將產生嵌套列表的第二個條目。 我對代碼的解釋是否正確? 我的困惑主要來自於在__iter__的定義中包含一個 for 循環。

例如,如果我們現在應用 list() function,我們得到:

list(store) # returns [1, 1.1, 1.3]

我試圖找出 list() function 是如何運作的,但我想它將 object 的條目附加到一個空列表(或其中的一些)。

也許插入一些打印語句將提供更多信息:

class OdeStore:
    def __init__(self,data):
        self.data=data #list of form [[t0,u0],[t1,u1]...]
    def __iter__(self):
        print("  starting __iter__")
        for t,u in self.data: #specify the data iterated over
            print(f"  iter at {t},{u}, returning {u}")
            yield u #how it is yielded
        
print("iterating over OdeStore")
store=OdeStore([[0,1],[0.1,1.1],[0.2,1.3]])
for u in store:
   print(u)

print("starting list")
l = list(store)
print(f"list: {l}")

Output:

iterating over OdeStore
  starting __iter__
  iter at 0,1, returning 1
1
  iter at 0.1,1.1, returning 1.1
1.1
  iter at 0.2,1.3, returning 1.3
1.3
starting list
  starting __iter__
  iter at 0,1, returning 1
  iter at 0.1,1.1, returning 1.1
  iter at 0.2,1.3, returning 1.3
list: [1, 1.1, 1.3]

您可以看到對__iter__的初始調用(在 for 循環開始時進行)並且__iter__內的 for 循環被 yield 調用“暫停”。 從概念上講,執行的 state 由 yield 調用保存,將一個值返回給 for 循環,並在下一次 for 循環調用迭代器時使用保存的上下文繼續執行。

我試圖找出 list() function 是如何運作的,但我想它將 object 的條目附加到一個空列表(或其中的一些)。

我相信這在概念層面上是正確的。 從 output 可以看出,在列表構建期間,會創建一個迭代器並遍歷 OdeStore。

也許以這種方式分解它會使它更加具體。 讓我們把我們的腳本改成這樣:

class OdeStore:
    def __init__(self,data):
        self.data=data #list of form [[t0,u0],[t1,u1]...]
    def __iter__(self):
        print("  starting __iter__")
        for index in range(0, len(self.data)):
            print(f"  iter at index {index}, returning {self.data[index][1]}")
            yield self.data[index][1]
        #for t,u in self.data: #specify the data iterated over
        #    print(f"  iter at {t},{u}, returning {u}")
        #    yield u #how it is yielded
        
store=OdeStore([[0,1],[0.1,1.1],[0.2,1.3]])
print("Creating iterator")
iter = iter(store)
print("calling next 1st time")
print(next(iter))
print("calling next 2nd time")
print(next(iter))
print("calling next 3rd time")
print(next(iter))
print("calling next 4th time")
print(next(iter))

Output:

Creating iterator
calling next 1st time
  starting __iter__
  iter at index 0, returning 1
1
calling next 2nd time
  iter at index 1, returning 1.1
1.1
calling next 3rd time
  iter at index 2, returning 1.3
1.3
calling next 4th time
Traceback (most recent call last):
  File "./odestore.py", line 25, in <module>
    print(next(iter))
StopIteration

從概念上講,每個yield都在節省指數並返回計算值。 當再次調用迭代器時,這個存儲的索引會增加(因為__iter__中的for循環)。 調用 yield 保存index的新值並返回計算值。 當我們用完值時, __iter__返回而不是產生,並且迭代器實現 class (稱為generator )引發StopIteration異常。

暫無
暫無

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

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