[英]Python 3: How to write a __iter__ method for derived class so that it extends on the behaviour of the base class' __iter__ method
[英]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.