迭代遵循迭代器協(xié)議時,,需要Python迭代器對象支持兩種方法,。 __iter__返回迭代器對象本身。這用于for 和in語句,。 __next__方法從迭代器返回下一個值,。如果沒有其他項目要返回,則應引發(fā)StopIteration異常,。 class Counter(object): def __init__(self, low, high): self.current = low self.high = high def __iter__(self): 'Returns itself as an iterator object' return self def __next__(self): 'Returns the next value till current is lower than high' if self.current > self.high: raise StopIteration else: self.current += 1 return self.current - 1 現(xiàn)在,,我們可以在代碼中使用此迭代器。
請記住,,迭代器對象只能使用一次,。這意味著在它 一次引發(fā)StopIteration之后,它將繼續(xù)引發(fā)相同的異常,。 >>> c = Counter(5,6)>>> next(c)5>>> next(c)6>>> next(c)Traceback (most recent call last):File '<stdin>', line 1, in <module>File '<stdin>', line 11, in nextStopIteration>>> next(c)Traceback (most recent call last):File '<stdin>', line 1, in <module>File '<stdin>', line 11, in nextStopIteration 在前面看到的for循環(huán)示例中使用迭代器,,以下示例嘗試在后臺顯示代碼。
發(fā)電機在本節(jié)中,,我們將學習Python生成器,。它們是在Python 2.3中引入的。這是一種使用函數(shù)的關鍵字yield創(chuàng)建迭代器的簡便方法,。 >>> def my_generator():... print('Inside my generator')... yield 'a'... yield 'b'... yield 'c'...>>> my_generator()<generator object my_generator at 0x7fbcfa0a6aa0> 在上面的示例中,,我們使用yield語句創(chuàng)建了一個簡單的生成器。就像使用其他迭代器一樣,,我們可以在for循環(huán)中使用它,。
在下一個示例中,我們將使用生成器函數(shù)創(chuàng)建相同的Counter類,,并將其用于for循環(huán)中,。 def counter_generator(low, high): while low <= high: yield low low += 1 >>> for i in counter_generator(5,10):... print(i, end=' ')...5 6 7 8 9 10 在while循環(huán)中,當?shù)竭_yield語句時,,將返回low的值,,并暫停生成器狀態(tài)。在第二個下一個調用期間,,生成器恢復到之前凍結的位置,,然后將low的值增加1。它繼續(xù)while循環(huán),,并再次返回yield語句,。 調用生成器函數(shù)時,它將返回* generator *對象,。如果在此對象上調用* dir *,,您會發(fā)現(xiàn)它包含__iter__和* __ next __ *方法以及其他方法。
如果大家在學習中遇到困難,,想找一個python學習交流環(huán)境,,可以加入我們的python裙,關注小編,,并私信“01”即可進裙,,領取python學習資料,會節(jié)約很多時間,,減少很多遇到的難題,。我們主要使用生成器進行延遲評估。這樣,,生成器就成為處理大量數(shù)據(jù)的好方法,。如果您不想將所有數(shù)據(jù)加載到內存中,則可以使用生成器,,該生成器將一次向您傳遞每個數(shù)據(jù),。 該示例的最大示例之一是os.path.walk()函數(shù),該函數(shù)使用回調函數(shù)和當前的os.walk生成器,。使用生成器實現(xiàn)可節(jié)省內存,。 我們可以有生成無限值的生成器。以下是一個這樣的示例,。 >>> def infinite_generator(start=0):... while True:... yield start... start += 1...>>> for num in infinite_generator(4):... print(num, end=' ')... if num > 20:... break...4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 如果我們回到my_generator的示例,,我們將發(fā)現(xiàn)生成器的一項功能。它們不可重復使用,。
創(chuàng)建可重用生成器的一種方法是不持有任何狀態(tài)的基于對象的生成器,。任何具有__iter__方法的類都可以產(chǎn)生數(shù)據(jù),可以用作對象生成器,。在下面的示例中,,我們將重新創(chuàng)建計數(shù)器生成器。 >>> class Counter(object):... def __init__(self, low, high):... self.low = low... self.high = high... def __iter__(self):... counter = self.low... while self.high >= counter:... yield counter... counter += 1...>>> gobj = Counter(5, 10)>>> for num in gobj:... print(num, end=' ')...5 6 7 8 9 10>>> for num in gobj:... print(num, end=' ')...5 6 7 8 9 10 生成器表達式在本節(jié)中,,我們將學習生成器表達式,,它是列表理解和生成器的高性能,內存高效的概括,。 例如,,我們將嘗試對1到9之間所有數(shù)字的平方求和。
該示例實際上首先在內存中創(chuàng)建一個平方值列表,,然后對其進行迭代,,最后在求和后釋放內存。如果列表很大,,您可以了解內存使用情況,。 我們可以使用生成器表達式來節(jié)省內存使用量,。 sum(x*x for x in range(1,10)) 生成器表達式的語法表明,始終必須直接在一組括號內,,并且兩邊都不能有逗號,。這基本上意味著以下兩個示例都是有效的生成器表達式用法示例。
我們可以鏈接生成器或生成器表達式,。在以下示例中,,我們將讀取文件* / var / log / cron *,并將查找是否有任何特定作業(yè)(在示例中,,我們正在搜索anacron)是否成功運行,。 我們可以使用shell命令tail -f / var / log / cron | grep anacron進行相同的操作 >>> jobtext = 'anacron'>>> all_lines = (line for line in open('/var/log/cron', 'r') )>>> job = ( line for line in all_lines if line.find(jobtext) != -1)>>> text = next(job)>>> text'May 6 12:17:15 dhcp193-104 anacron[23052]: Job `cron.daily' terminated\n'>>> text = next(job)>>> text'May 6 12:17:15 dhcp193-104 anacron[23052]: Normal exit (1 job run)\n'>>> text = next(job)>>> text'May 6 13:01:01 dhcp193-104 run-parts(/etc/cron.hourly)[25907]: starting 0anacron\n' 您可以在各行中編寫一個for循環(huán)。 閉包閉包不過是由另一個函數(shù)返回的函數(shù),。我們使用閉包刪除代碼重復,。在下面的示例中,我們創(chuàng)建一個簡單的閉包以添加數(shù)字,。
加法器是一種閉包,,它將給定的數(shù)字添加到預定義的數(shù)字中。 裝飾器裝飾器是一種向某些對象動態(tài)添加一些新行為的方法,。我們通過使用閉包在Python中實現(xiàn)了相同的目的,。 在該示例中,我們將創(chuàng)建一個簡單的示例,,該示例將在函數(shù)執(zhí)行前后打印一些語句,。 >>> def my_decorator(func):... def wrapper(*args, **kwargs):... print('Before call')... result = func(*args, **kwargs)... print('After call')... return result... return wrapper...>>> @my_decorator... def add(a, b):... 'Our add function'... return a + b...>>> add(1, 3)Before callAfter call4
|
|