什么叫可迭代物件?
- 不專業:可以直接作用于
for回圈的物件,統稱為可迭代物件:Iterable - 稍微專業:通過 Python 內置方法
isinstance(obj, Iterable)進行判斷, 若回傳為True則是,反之則不是; - 專業解釋:該物件含有
__iter__方法則稱為可迭代物件;
from collections import Iterable, Iterator
class Classmate(object):
def __init__(self):
self.name = list()
def add(self, name):
self.name.append(name)
if __name__ == '__main__':
c = Classmate()
c.add("張三")
c.add("李四")
c.add("王五")
print("c 是否是可迭代物件:", isinstance(c, Iterable))
# 測驗結果如下:
# 實體 c 中不含有 __iter__ 方法時,判斷顯示為 False,即不可迭代物件
c 是否是可迭代物件: False
# 當給類 Classmate 加上 __iter__方法時
from collections import Iterable, Iterator
class Classmate(object):
def __init__(self):
self.name = list()
def add(self, name):
self.name.append(name)
def __iter__(self):
pass
if __name__ == '__main__':
c = Classmate()
c.add("張三")
c.add("李四")
c.add("王五")
print("c 是否是可迭代物件:", isinstance(c, Iterable)) # 當注釋掉類中的 __iter__ ,這里判斷會變為 False
# 測驗結果如下:
# 實體 c 中不含有 __iter__ 方法時,判斷顯示為不可迭代物件
c 是否是可迭代物件: True
什么叫迭代器?
- 不專業1:可以被
next()函式呼叫并不斷回傳下一個值的物件稱為迭代器; - 不專業2:通過
iter()函式作用于可迭代物件之后生成的物件稱為迭代器; - 稍微專業:通過 Python 內置方法
isinstance(obj, Iterator)進行判斷, 若回傳為True則是,反之則不是; - 專業解釋:通過
iter()函式作用于可迭代物件之后生成的物件,并且該物件含有__iter__和__next__方法;
from collections import Iterable, Iterator
class Classmate(object):
def __init__(self):
self.name = list()
def add(self, name):
self.name.append(name)
def __iter__(self):
# pass
return ClassIterator()
class ClassIterator(object):
def __iter__(self):
pass
def __next__(self):
pass
if __name__ == '__main__':
c = Classmate()
c.add("張三")
c.add("李四")
c.add("王五")
print("c 是否是可迭代物件:", isinstance(c, Iterable)) # 當注釋掉類中的 __iter__ ,這里判斷會變為 False
print("c 是否是迭代器:", isinstance(c, Iterator))
d = iter(c)
print("d 是否是迭代器:", isinstance(d, Iterator))
# 測驗結果如下:
c 是否是可迭代物件: True
c 是否是迭代器: False
d 是否是迭代器: True # 當注釋掉 類 ClassIterator 中的任意一個方法,該回傳值為 False 或報錯
那么問題來了,什么時候可以用 for 回圈去從可迭代物件或者迭代器中進行取值呢?
先弄清楚,不論是 for 回圈是從可迭代物件還是迭代器中取值,都是呼叫的該物件的 __next__ 方法回傳的值,那問題來了,可迭代物件中比如上述代碼中的類 Classmate 沒有 __next__ 方法就不能取值了?這里答案是否定的,因為類 Classmate 中還有 __iter__ 方法, 呼叫該方法若回傳的物件中有 __next__ 方法,仍舊可以取該方法的回傳值;
class Classmate(object):
def __init__(self):
self.name = list()
def add(self, name):
self.name.append(name)
def __iter__(self):
# pass
return ClassIterator()
class ClassIterator(object):
def __iter__(self):
pass
def __next__(self):
return 111
if __name__ == '__main__':
c = Classmate()
c.add("張三")
c.add("李四")
c.add("王五")
for i in c:
print(i)
# 測驗結果如下:
控制臺會不斷列印類 ClassIterator 中的 __next__ 方法的輸出 111,這個結果肯定不是我們希望的,我們希望列印我們添加的名稱;
略
于是我們繼續改造代碼如下:
class Classmate(object):
def __init__(self):
self.name = list()
def add(self, name):
self.name.append(name)
def __iter__(self):
# pass
return ClassIterator(self)
class ClassIterator(object):
def __init__(self, obj):
self.obj = obj
self.num = 0
def __iter__(self):
pass
def __next__(self):
res = self.obj.name[self.num]
self.num += 1
return res
if __name__ == '__main__':
c = Classmate()
c.add("張三")
c.add("李四")
c.add("王五")
for i in c:
print(i)
# 測驗結果如下:
Traceback (most recent call last):
張三
File "/Users/wawa/Desktop/code/03協程/迭代器.py", line 46, in <module>
李四
for i in c:
王五
File "/Users/wawa/Desktop/code/03協程/迭代器.py", line 32, in __next__
res = self.obj.name[self.num]
IndexError: list index out of range
繼續優化:
class Classmate(object):
def __init__(self):
self.name = list()
def add(self, name):
self.name.append(name)
def __iter__(self):
# pass
return ClassIterator(self)
class ClassIterator(object):
def __init__(self, obj):
self.obj = obj
self.num = 0
def __iter__(self):
pass
def __next__(self):
if self.num < len(self.obj.name):
res = self.obj.name[self.num]
self.num += 1
return res
else:
raise StopIteration
if __name__ == '__main__':
c = Classmate()
c.add("張三")
c.add("李四")
c.add("王五")
for i in c:
print(i)
# 測驗結果如下:
張三
李四
王五
到這里了好像都實作了,那么問題又來了,可以把上面的兩個類用一個類實作嗎?
真的是一個好問題~其實這里也是手寫迭代器實作 for 回圈的邏輯,繼續優化代碼如下:
class Classmate(object):
def __init__(self):
self.name = list()
self.num = 0
def add(self, name):
self.name.append(name)
def __iter__(self):
# pass
# return ClassIterator(self)
return self
def __next__(self):
if self.num < len(self.name):
res = self.name[self.num]
self.num += 1
return res
else:
raise StopIteration
if __name__ == '__main__':
c = Classmate()
c.add("張三")
c.add("李四")
c.add("王五")
for i in c:
print(i)
# 測驗結果如下:
張三
李四
王五
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/256688.html
標籤:python
上一篇:IntelliJ IDEA 查看類繼承關系圖,太強大了!
下一篇:逆向迷宮題總結(持續更新) 2020華南師大CTF新生賽maze,攻防世界新手區:NJUPT CTF 2017,BUUCTF:不一樣的flag
