前言
上次我們簡單分享了迭代器和生成器,本次我們來更加深入的了解相關(guān)概念和使用方法扔亥,希望能對你有所幫助场躯。
自定義迭代器
首先谈为,我們來看看怎么自定義迭代器,自定義迭代器的類需要下面幾個組成踢关。
(1)類中需要定義iter和next魔術(shù)方法伞鲫。
(2)iter魔術(shù)方法返回對象本身。
(3)next方法返回下一個數(shù)據(jù)签舞,如果沒有數(shù)據(jù)秕脓,就報異常StopIteration。
class Test:
def __init__(self):
self.counter = 0
def __iter__(self):
return self
def __next__(self):
self.counter += 1
if self.counter == 3:
raise StopIteration
return self.counter
t = Test()
print(next(t))
print(next(t))
print(next(t))
1
2
StopIteration
當然儒搭,我們可以直接使用for循環(huán)來調(diào)用這個迭代器對象吠架。
for i in t:
print(i)
1
2
for循環(huán)里面到底是怎么執(zhí)行的了?首先for循環(huán)會先調(diào)用對象的iter魔術(shù)方法搂鲫,返回一個迭代器對象傍药,然后不斷調(diào)用next魔術(shù)方法(異常就停止循環(huán))。
生成器
我們之前學習過魂仍,函數(shù)中有yield關(guān)鍵字拐辽,那這個函數(shù)就是生成器。
def func():
yield 1
yield 2
f = func()
print(next(f))
print(next(f))
1
2
其實這個生成器對象內(nèi)部其實是調(diào)用的生成器類generator創(chuàng)建的對象蓄诽,生成器類的內(nèi)部其實也聲明了iter和next魔術(shù)方法薛训。
生成器也完全符合迭代器聲明的規(guī)則,所以仑氛,生成器也是一種特殊的迭代器乙埃。
可迭代對象
最后,我們再聊聊可迭代對象锯岖,我們都知道介袜,列表就是可迭代對象。
l = [1, 2, 3]
for i in l:
print(i)
字符串出吹,字典等等能夠循環(huán)的遇伞,都是可迭代對象。其定義是捶牢,如果類中有iter魔術(shù)方法鸠珠,并且返回的是迭代器對象,那這個類創(chuàng)建的對象就是可迭代對象秋麸。
class Test:
def __init__(self):
self.counter = 0
def __iter__(self):
return self
def __next__(self):
self.counter += 1
if self.counter == 3:
raise StopIteration
return self.counter
class Foo:
def __iter__(self):
return Test()
foo = Foo()
for item in foo:
print(item)
1
2
這里的foo就是可迭代對象渐排,當使用for循環(huán)時,先調(diào)用iter魔術(shù)方法灸蟆,返回一個迭代器對象驯耻,接著就是不斷的調(diào)用next魔術(shù)方法返回值。
我們可以驗證下,列表是可迭代對象可缚,那他就應該有iter方法霎迫,沒有next方法。
l = [1, 2, 3]
print(dir(l))
#['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
print(dir(l.__iter__()))
調(diào)用iter方法后帘靡,就會有iter和next方法了知给。
自定義range函數(shù)
學了這么多,我們來自定義一個range函數(shù)來鞏固下學習內(nèi)容测柠。
class RangeIter:
def __init__(self, num):
self.num = num
self.counter = -1
def __iter__(self):
return self
def __next__(self):
self.counter += 1
if self.counter == self.num:
raise StopIteration
return self.counter
class Xrange:
def __init__(self, maxnum):
self.maxnum = maxnum
def __iter__(self):
return RangeIter(self.maxnum)
for i in Xrange(10):
print(i)
生成器也可以實現(xiàn)該功能炼鞠。
class Xrange:
def __init__(self, maxnum):
self.maxnum = maxnum
def __iter__(self):
counter = 0
while counter < self.maxnum:
yield counter
counter += 1
for i in Xrange(5):
print(i)
今天的分享就到這了缘滥,我們下期再見~