- Python進階編程:編寫更高效、優雅的Python代碼
- 劉宇宙 謝東 劉艷
- 561字
- 2021-04-30 12:39:48
4.1.3 實現迭代協議
下面構建一個支持迭代操作的自定義對象,并找到一個能實現迭代協議的簡單方法。
截至目前,在一個對象上實現迭代最簡單的方式是使用生成器函數。在4.1.2節中,使用Node類表示樹型數據結構,實現了以深度優先遍歷樹形節點的生成器,代碼(real_agreement.py)如下:
class Node: def __init__(self, value): self._value = value self._children = [] def __repr__(self): return f'Node({self._value})' def add_child(self, node): self._children.append(node) def __iter__(self): return iter(self._children) def depth_first(self): yield self for c in self: yield from c.depth_first() if __name__ == '__main__': root = Node(0) child_1 = Node(1) child_2 = Node(2) root.add_child(child_1) root.add_child(child_2) child_1.add_child(Node(3)) child_1.add_child(Node(4)) child_2.add_child(Node(5)) for ch in root.depth_first(): print(f'child is: {ch}')
執行py文件,輸出結果如下:
child is: Node(0) child is: Node(1) child is: Node(3) child is: Node(4) child is: Node(2) child is: Node(5)
上述代碼中,depth_first()方法簡單直觀。首先返回自己本身并迭代每一個子節點,然后再通過調用子節點的depth_first()方法(使用yield from語句)返回對應元素。
Python的迭代協議要求一個__iter__()方法返回一個特殊的迭代器對象,這個迭代器對象實現了__next__()方法并通過StopIteration異常標識迭代完成。不過,實現過程通常會比較煩瑣。以下示例展示了如何使用一個關聯迭代器類重新實現depth_first()方法。
class Node2: def __init__(self, value): self._value = value self._children = [] def __repr__(self): return f'Node({self._value})' def add_child(self, node): self._children.append(node) def __iter__(self): return iter(self._children) def depth_first(self): return DepthFirstIterator(self) class DepthFirstIterator(object): def __init__(self, start_node): self._node = start_node self._children_iter = None self._child_iter = None def __iter__(self): return self def __next__(self): # Return myself if just started; create an iterator for children if self._children_iter is None: self._children_iter = iter(self._node) return self._node # If processing a child, return its next item elif self._child_iter: try: next_child = next(self._child_iter) return next_child except StopIteration: self._child_iter = None return next(self) # Advance to the next child and start its iteration else: self._child_iter = next(self._children_iter).depth_first() return next(self)
DepthFirstIterator類和前面使用生成器的版本工作原理類似,但是它寫起來很煩瑣,因為迭代器必須在迭代處理過程中維護大量的狀態信息。在實際應用中,沒人愿意寫這么晦澀的代碼,而是將迭代器定義為一個生成器。
推薦閱讀
- 手機安全和可信應用開發指南:TrustZone與OP-TEE技術詳解
- PHP動態網站程序設計
- Qt 5 and OpenCV 4 Computer Vision Projects
- Flink SQL與DataStream入門、進階與實戰
- Kotlin從基礎到實戰
- Android開發案例教程與項目實戰(在線實驗+在線自測)
- 大學計算機基礎實驗指導
- 軟件測試實用教程
- Learning R for Geospatial Analysis
- 后臺開發:核心技術與應用實踐
- Extending Unity with Editor Scripting
- ASP.NET Web API Security Essentials
- Python預測之美:數據分析與算法實戰(雙色)
- 基于JavaScript的WebGIS開發
- H5頁面設計與制作(全彩慕課版·第2版)