Python3.4 Tutorial9 - Classes (Part 4)
9.9 迭代器(Iterators)
你可能已經意識到了,大多數的容器物件都是可以使用for語句遍歷的:
for element in [1, 2, 3]: print(element) for element in (1, 2, 3): print(element) for key in {'one':1, 'two':2}: print(key) for char in "123": print(char) for line in open("myfile.txt"): print(line, end='')
這樣的訪問風格是清晰、簡潔而且方便的。迭代器的使用很普遍而且在Python中是統一的。for語句幕後就是對容器物件呼叫的itor()。這個函式返回一個迭代器物件,它定義了方法_next_()在每次呼叫時訪問容器中的一個元素。當沒有更多元素時,_next_()引發一個StopIteration異常,來告訴for迴圈終止遍歷。你可以使用內建函式next()來呼叫_next_()方法;這個例子展示了它的所有工作內容:
>>> s = 'abc' >>> it = iter(s) >>> it <iterator object at 0x00A1DB50> >>> next(it) 'a' >>> next(it) 'b' >>> next(it) 'c' >>> next(it) Traceback (most recent call last): File "<stdin>", line 1, in ? next(it) StopIteration
看完迭代器協議後面的機制,再向你的類中新增迭代器行為就很容易了。定義一個_iter_()方法,它返回一個帶有_next_()方法的物件。如果這個類定義了_next_(),那麼_iter_()可以直接返回self
:
class Reverse: """Iterator for looping over a sequence backwards.""" def __init__(self, data): self.data = data self.index = len(data) def __iter__(self): return self def __next__(self): if self.index == 0: raise StopIteration self.index = self.index - 1 return self.data[self.index]
>>> rev = Reverse('spam') >>> iter(rev) <__main__.Reverse object at 0x00A1DB50> >>> for char in rev: ... print(char) ... m a p s
9.10 生成器(Generators)
生成器是建立迭代器簡單而有效的工具。它的寫法和普通的函式類似,但是在返回資料的時候使用yield語句。next()每次呼叫到它的時候,生成器就會從它中斷的地方恢復執行(resume)(它會記錄下所有資料的值和最後執行的一條語句)。用一個例子來展示建立生成器是多麼簡單:
def reverse(data): for index in range(len(data)-1, -1, -1): yield data[index]
>>> for char in reverse('golf'): ... print(char) ... f l o g
任何可以用生成器做到的事,都可用用上一節提到的基於類的迭代器完成。生成器會如此簡潔是因為_iter_()和_next_()方法是自動建立的。
另一個關鍵特性是區域性變數和執行狀態是兩次呼叫間被自動儲存的。這使得函式更容易編寫,並且比使用self.index
和self.data
這樣的例項變數要簡潔的多。
在生成器中斷的時候除了能夠自動建立方法、儲存程式狀態之外,也會自動引發StopIteration異常。總結一下,這些特性使得建立一個和普通函式沒有區別的迭代器變得容易。
9.10 生成器表示式(Generator Expressions)
一些簡單的生成器可以編寫的像表示式一樣簡潔,只需要使用一種類似於列表生成式(list comprehensions)的語法,但是要把中括號[]替換成小括號()。這些表示式是為封閉函式需要立即使用生成器的情況而設計的。生成器表示式更簡潔但是和完整的生成器定義相比功能較弱,它往往比等價的列表生成式更節約記憶體。
例子:
>>> sum(i*i for i in range(10)) # sum of squares 285 >>> xvec = [10, 20, 30] >>> yvec = [7, 5, 3] >>> sum(x*y for x,y in zip(xvec, yvec)) # dot product 260 >>> from math import pi, sin >>> sine_table = {x: sin(x*pi/180) for x in range(0, 91)} >>> unique_words = set(word for line in page for word in line.split()) >>> valedictorian = max((student.gpa, student.name) for student in graduates) >>> data = 'golf' >>> list(data[i] for i in range(len(data)-1, -1, -1)) ['f', 'l', 'o', 'g']
相關文章
- Python3.4 Tutorial9 - Classes (Part 3)Python
- Python3.4 Tutorial9 - Classes (Part 2)Python
- Python3.4 Tutorial9 - Classes (Part 1)Python
- Python3.4 Tutorial11 - Brief Tour of the Standard Library – Part IIPython
- [翻譯]The Neophyte's Guide to Scala Part 12: Type ClassesGUIIDE
- Type classes in Scala
- 核心編譯part4編譯
- Study Plan For Algorithms - Part4Go
- IDAPython 讓你的生活更滋潤 – Part 3 and Part 4Python
- [SwiftUI 100天] BetterRest · part4SwiftUIREST
- 深入淺出Rust-Future-Part-4Rust
- Canvas 基礎 - 粒子動畫 Part4Canvas動畫
- django入門-表單-part4Django
- Android文字時鐘 — Part4Android
- [MetalKit]5-Using-MetalKit-part-4使用MetalKit4
- python3.4之決策樹Python
- [SwiftUI 100天] Bucket List - part4SwiftUI
- 【譯】[SwiftUI 100 天] Animations - part4SwiftUI
- 3 About Kernels and Traits ClassesAI
- Linux_java_呼叫classesLinuxJava
- DBReader/Classes/LogonGo
- python3.4支援xp麼Python
- Android開發貼士集合(Part 1~4)Android
- PostgreSQL DBA(46) - PG Operator classes and familiesSQL
- [ES6深度解析]12:Classes
- Python “黑魔法” 之 Meta ClassesPython
- python3.4連線oracle資料庫PythonOracle資料庫
- ViCANdo新版本釋出(PART4)| QML整合
- Oracle 20C Concepts(Part V-4)Oracle
- centOS學習part4:安裝配置vsftpCentOSFTP
- 美國之音1500基礎聽力詞彙(part 4)
- Python3.4中文手冊chm地址Python
- emacs作為python3.4 IDE的配置MacPythonIDE
- Go for PHP Developers: Structs vs Classes (翻譯)GoPHPDeveloperStruct
- Function 與 Classes 元件的區別在哪?Function元件
- lecture8 Template Classes + Const Correctness
- XtraBackup工具詳解 Part 4 XtraBackup許可權及配置
- 圖說比特幣 Part 4:如何儲存BlockHeaders?比特幣BloCHeader