[轉載] Python進階:設計模式之迭代器模式

參考鏈接: Python中的迭代器

在軟件開發領域中,人們經常會用到這一個概念——“設計模式”(design pattern),它是一種針對軟件設計的共性問題而提出的解決方案。在一本圣經級的書籍《設計模式:可復用面向對象軟件的基礎》(1991年,Design Patterns - Elements of Reusable Object-Oriented Software)中,它提出了23種設計模式。迭代器模式就是其中的一種,在各種編程語言中都得到了廣泛的應用。?

本文將談談 Python 中的迭代器模式,主要內容:什么是迭代器模式、Python 如何實現迭代器模式、itertools 模塊創建迭代器的方法、其它運用迭代器的場景等等,期待與你共同學習進步。?

1、什么是迭代器模式??

維基百科有如下定義:?

?

?迭代器是一種最簡單也最常見的設計模式。它可以讓用戶透過特定的接口巡訪容器中的每一個元素而不用了解底層的實現。——維基百科?

?

簡單地說,迭代器模式就是一種通用性的可以遍歷容器類型(如序列類型、集合類型等)的實現方式。使用迭代器模式,可以不關心遍歷的對象具體是什么(如字符串、列表、字典等等),也不需要關心遍歷的實現算法是什么,它關心的是從容器中遍歷/取出元素的結果。?

按遍歷方式劃分,迭代器可分為內部迭代器與外部迭代器,它們的區別在于執行迭代動作與維持迭代狀態的不同。?

通常而言,迭代器是一次性的,當迭代過一輪后,再次迭代將獲取不到元素。?

2、Python的迭代器模式?

由于迭代器模式的使用太常見了,所以大多數編程語言都給常見的容器類型實現了它,例如 Java 中的 Collection,List、Set、Map等。在 Java 中使用迭代器遍歷 List 可以這么寫:?

List<String> list = new ArrayList<>();

Iterator<String> iterator = list.iterator();

while(iterator.hasNext()){

? ? System.out.println(iterator.next());

}

?

ArrayList 類通過自身的 iterator() 方法獲得一個迭代器 iterator,然后由該迭代器實例來落實遍歷過程。?

Python 當然也應用了迭代器模式,但它的實現思路跟上例卻不太一樣。?

首先,Python 認為遍歷容器類型并不一定要用到迭代器,因此設計了可迭代對象。?

list = [1,2,3,4]

for i in list:

? ? print(i,end=" ") # 1 2 3 4

for i in list:

? ? print(i,end=" ") # 1 2 3 4

?

上例中的 list 是可迭代對象(Iterable),但并不是迭代器(雖然在底層實現時用了迭代器的部分思想)。Python 抓住了迭代器模式的本質,即是“迭代”,賦予了它極高的地位。?

如此設計的好處顯而易見:(1)寫法簡便,用意直白;(2)可重復迭代,避免一次性迭代器的缺陷;(3)不需要創建迭代器,減少開銷。?

可迭代對象可看作是廣義的迭代器,同時,Python 也設計了普通意義的狹義的迭代器。?

list = [1,2,3,4]

it = iter(list)

for i in it:

? ? print(i,end=" ") # 1 2 3 4

for i in it:

? ? print(i,end=" ") # 無輸出

?

上例中的 iter() 方法會將可迭代對象變成一個迭代器。從輸出結果可以看出,該迭代器的迭代過程是一次性的。?

由此看來,Python 其實是將“迭代器模式”一拆為二來實現:一是可迭代思想,廣泛播種于容器類型的對象中,使它們都可迭代;一是迭代器,一種特殊的可迭代對象,承擔普通意義上的迭代器所特有的迭代任務。?

同時,它還提供了將可迭代對象轉化為迭代器的簡易方法,如此安排,真是將迭代器模式的效力發揮到了極致。(關于可迭代對象與迭代器的更多區別、以及它們的實現原理,請參見《Python進階:迭代器與迭代器切片》)?

3、創建迭代器?

創建迭代器有如下方式:(1)iter() 方法,將可迭代對象轉化成迭代器;(2)__iter__() 與 __next__() 魔術方法,定義類實現這兩個魔術方法;(3)itertools 模塊,使用內置模塊生成迭代器;(4)其它創建方法,如 zip() 、map() 、enumerate() 等等。?

四類方法各有適用場所,本節重點介紹 itertools 模塊。它可以創建三類迭代器:無限迭代器、有限迭代器與組合迭代器。?

3.1 無限迭代器?

count(start=0, step=1) :創建一個從 start (默認值為 0) 開始,以 step (默認值為 1) 為步長的的無限整數迭代器。?

cycle(iterable) :對可迭代對象的元素反復執行循環。?

repeat(object [,times]) :反復生成 object 至無限,或者到給定的 times 次。?

import itertools

co = itertools.count()

cy = itertools.cycle('ABC')

re = itertools.repeat('A', 30)

?

# 注意:請分別執行;以下寫法未加終止判斷,只能按 Ctrl+C 退出

for n in co:

? ? print(n,end=" ")? # 0 1 2 3 4......

for n in cy:

? ? print(n,end=" ")? # A B C A B C A B......

for n in re:

? ? print(n,end=" ")? # A A A A A A A A....(30個)

?

3.2 有限迭代器?

?

以上方法,比較常用的有:chain() 將多個可迭代對象(可以是不同類型)連接成一個大迭代器;compress() 方法根據真假過濾器篩選元素;groupby() 把迭代器中相鄰的重復元素挑出來放在一起;islice() 方法返回迭代器切片(用法參見《Python進階:迭代器與迭代器切片》);tee() 方法根據可迭代對象創建 n 個(默認2個)迭代器副本。?

for c in itertools.chain('ABC', [1,2,3]):

? ? print(c,end=" ")

# 輸出結果:A B C 1 2 3

?

for c in itertools.compress('ABCDEF', [1, 1, 0, 1, 0, 1]):

? ? print(c,end=" ")

# 輸出結果:A B D F

?

for key, group in itertools.groupby('aaabbbaaccd'):

? ? print(key, ':', list(group))

# 輸出結果:

a : ['a', 'a', 'a']

b : ['b', 'b', 'b']

a : ['a', 'a']

c : ['c', 'c']

d : ['d']

?

itertools.tee('abc', 3)

# 輸出結果:(<itertools._tee at 0x1fc72c08108>,

?<itertools._tee at 0x1fc73f91d08>,

?<itertools._tee at 0x1fc73efc248>)

?

3.3 組合迭代器?

product() :求解多個可迭代對象的笛卡爾積。?

permutations() :求解可迭代對象的元素的全排列。?

combinations():求解可迭代對象的元素的組合。?

for i in itertools.product('ABC', [1,2]):

? ? print(i, end=" ")

# 輸出結果:('A', 1) ('A', 2) ('B', 1) ('B', 2) ('C', 1) ('C', 2)

?

for i in itertools.permutations('ABC', 2):

? ? print(i, end=" ")

# 輸出結果:('A', 'B') ('A', 'C') ('B', 'A') ('B', 'C') ('C', 'A') ('C', 'B')

?

for i in itertools.combinations('ABC', 2):

? ? print(i, end=" ")

# 輸出結果:('A', 'B') ('A', 'C') ('B', 'C')

?

for i in itertools.combinations('ABCD', 3):

? ? print(i, end=" ")

# 輸出結果:('A', 'B', 'C') ('A', 'B', 'D') ('A', 'C', 'D') ('B', 'C', 'D')

?

4、強大的內置迭代器方法?

迭代器模式的使用場景實在太普遍了,而 Python 也為迭代器的順利使用而提供了很多便利的條件,本節將介紹相關的幾個內置方法。這些方法非常常用而且強大,是 Python 進階的必會內容。?

4.1 zip() 方法?

zip() 方法可以同時迭代多個序列,并各取一個元素,生成一個可返回元組的迭代器。此迭代器的長度以較短序列的長度保持一致,若想生成較長序列的長度,需要使用 itertools 模塊的 zip_longest() 方法。?

import itertools

?

a = [1, 2, 3]

b = ['w', 'x', 'y', 'z']

?

for i in zip(a,b):

? ? print(i,end=" ")? # (1, 'w') (2, 'x') (3, 'y')

?

# 空缺值以 None 填補

for i in itertools.zip_longest(a,b):

? ? print(i,end=" ")? # (1, 'w') (2, 'x') (3, 'y') (None, 'z')

?

4.2 enumerate() 方法?

enumerate() 方法接收一個序列類型參數,生成一個可返回元組的迭代器,元組內容是下標及其對應的元素值。它還可接收一個可選參數,指定下標的起始值,默認是0 。?

注意:眾所周知,Python 中序列的索引值從 0 開始,但是,enumerate() 可以達到改變起始索引數值的效果。?

seasons = ['Spring', 'Summer', 'Fall', 'Winter']

?

for i in enumerate(seasons):

? ? print(i,end=" ")??

#輸出結果:(0, 'Spring') (1, 'Summer') (2, 'Fall') (3, 'Winter')

?

for i in enumerate(seasons, start=7):

? ? print(i,end=" ")??

#輸出結果:(7, 'Spring') (8, 'Summer') (9, 'Fall') (10, 'Winter')

?

4.3 map() 方法?

map() 方法的參數是一個函數及一個或多個可迭代對象,它會將可迭代對象的元素映射到該函數中,然后迭代地運行該函數,返回結果也是一個迭代器。當存在多個可迭代對象參數時,迭代長度等于較短對象的長度。?

def square(x):

? ? return x ** 2

?

l = map(square, [1, 2, 3, 4, 5])

print(list(l))

# 輸出結果:[1, 4, 9, 16, 25]

?

m = map(lambda x, y: x + y, [1, 3, 5, 7, 9], [2, 4, 6, 8, 10, 2])

print(list(m))

# 輸出結果:[3, 7, 11, 15, 19]

?

4.4 filter() 方法?

filter() 方法的參數是一個判斷函數及一個可迭代對象,遍歷可迭代對象執行判斷函數,過濾下判斷為True 的元素,與它相對,若想保留判斷為 False 的元素,可使用 itertoole 模塊的 filterfalse() 方法。?

import itertools

?

fi = filter(lambda x: x%2, range(10))

ff = itertools.filterfalse(lambda x: x%2, range(10))

?

for i in fi:

? ? print(i,end=" ")

# 輸出結果:1 3 5 7 9

?

for i in ff:

? ? print(i,end=" ")

# 輸出結果:0 2 4 6 8

?

5. 小結?

迭代器模式幾乎是 23 種設計模式中最常用的設計模式,本文主要介紹了 Python 是如何運用迭代器模式,并介紹了 itertools 模塊生成迭代器的 18 種方法,以及 5 種生成迭代器的內置方法。?

相關鏈接:?

itertools模塊文檔:http://t.cn/R6cGtfw?

Python進階:迭代器與迭代器切片?

Python進階:全面解讀高級特性之切片!?

-----------------?

本文原創并首發于微信公眾號【Python貓】,后臺回復“愛學習”,免費獲得20+本精選電子書。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/540481.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/540481.shtml
英文地址,請注明出處:http://en.pswp.cn/news/540481.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

JavaScript | 如何為變量分配十進制,八進制和十六進制值?

Just like C programming language, we can assign integer value in the different format to the variable. 就像C編程語言一樣 &#xff0c;我們可以將不同格式的整數值分配給變量。 Assigning decimal value: It can be assigned simply without using any prefix. 分配十…

路由器DHCP和DHCP中繼的配置

路由器 DHCP和DHCP中繼的配置 路由器作為DHCP服務器&#xff1a; 1.配置router的地址&#xff1a;Route(config)# hostname gateway (更改主機名字) Gateway(config)# interface gigabitethernet 0/0 …

[轉載] 大數據分析Python For循環教程

參考鏈接&#xff1a; Python中的迭代器函數1 大數據分析Python除了循環遍歷列表之外&#xff0c;for循環還有很多其他功能&#xff0c;在現實世界的數據科學工作中&#xff0c;您可能需要將numpy數組和pandas DataFrames用于其他數據結構的循環。 大數據分析Python For循環教…

node.js 爬蟲入門總結

node.js爬蟲 前端同學可能向來對爬蟲不是很感冒&#xff0c;覺得爬蟲需要用偏后端的語言&#xff0c;諸如 php &#xff0c; python 等。當然這是在 nodejs 前了&#xff0c;nodejs 的出現&#xff0c;使得 Javascript 也可以用來寫爬蟲了。由于 nodejs 強大的異步特性&#xf…

數組重復次數最多的元素遞歸_使用遞歸計算鏈接列表中元素的出現次數

數組重復次數最多的元素遞歸Solution: 解&#xff1a; Required function: 所需功能&#xff1a; func_occurence ( node *temp) //recursive functionInput: 輸入&#xff1a; A singly linked list whose address of the first node is stored in a pointer, say head and…

SecureCRT中文亂碼解決方法

服務端export LANGzh_CN.UTF-8客戶端SecureCRT編碼選擇UTF-8客戶端SecureCRT字體選擇新宋體&#xff0c;字符集選擇中文總結&#xff1a;客戶端和服務端字符編碼一致&#xff0c;客戶端字體字符集支持轉載于:https://blog.51cto.com/leomars/1972669

[轉載] Python 迭代器 深入理解 與應用示例

參考鏈接&#xff1a; Python | 可迭代和迭代器之間的區別 本篇文章簡單談談可迭代對象&#xff0c;迭代器和生成器之間的關系。 三者簡要關系圖 可迭代對象與迭代器 剛開始我認為這兩者是等同的&#xff0c;但后來發現并不是這樣&#xff1b;下面直接拋出結論&#xff1a; 1…

Python程序查找表示O(1)復雜度的數字所需的位數

Problem statement 問題陳述 Find total Number of bits required to represent a number in binary 查找以二進制表示數字所需的總位數 Example 1: 范例1&#xff1a; input : 10output: 4Example 2: 范例2&#xff1a; input : 32output : 6Formula used: 使用的公式&am…

正則split

string content "第1行導入失敗&#xff0c;失敗原因為&#xff1a; 《加班原因》字段必填";string[] resultString Regex.Split(content, "失敗原因為&#xff1a;", RegexOptions.IgnoreCase);foreach (string i in resultString){Console.WriteLine(i…

將八進制數制轉換為二進制,十進制和十六進制數制

1)將八進制數制轉換為二進制數制 (1) Conversion of Octal Number System to Binary Number System) To convert octal numbers into binary numbers, we can use the relationship between octal and binary numbers. 要將八進制數轉換為二進制數&#xff0c;我們可以使用八進…

[轉載] Python的生成器

參考鏈接&#xff1a; Python中的生成器Generator Python的生成器 什么是生成器 創建python迭代器的過程雖然強大&#xff0c;但是很多時候使用不方便。生成器是一個簡單的方式來完成迭代。簡單來說&#xff0c;Python的生成器是一個返回可以迭代對象的函數。 怎樣創建生…

想提高用戶訪問的響應速度和成功率還不趕快學習CDN

2019獨角獸企業重金招聘Python工程師標準>>> 課程介紹 CDN可以將源站內容分發至最接近用戶的節點&#xff0c;使用戶可就近取得所需內容&#xff0c;提高用戶訪問的響應速度和成功率。解決因分布、帶寬、服務器性能帶來的訪問延遲問題&#xff0c;適用于站點加速、點…

[轉載] python迭代器、生成器和裝飾器

參考鏈接&#xff1a; 有效地在Python中使用迭代 文章目錄 生成器生成器表達式(generator expression)通過使用yield關鍵字定義生成器并行前戲高潮 迭代器迭代器概述iter()函數 創建迭代器創建一個迭代器(類)內置迭代器工具count無限迭代器cycle 無限迭代器&#xff0c;從一個…

java中的starts_Java Math類靜態double nextAfter(double starts,double direction)示例

java中的starts數學類靜態double nextAfter(雙向啟動&#xff0c;雙向) (Math Class static double nextAfter(double starts , double directions) ) This method is available in java.lang package. 此方法在java.lang包中可用。 This method is used to return the double …

Python 核心編程(第二版)——條件和循環

Python 中的 if 子句由三部分組成: 關鍵字本身&#xff0c;用于判斷結果真假的條件表達式&#xff0c; 以及當表達式為真或者非零時執行的代碼塊。if 語句的語法如下: if expression: expr_true_suite 單個 if 語句可以通過使用布爾操作符 and , or 和 not實現多重判斷條件或…

[轉載] 【python魔術方法】迭代器(__iter__和__next__)

參考鏈接&#xff1a; Python __iter __()和__next __()| 將對象轉換為迭代器 文章目錄 __iter__ 和 __next__真正的迭代器總結 python里面有很多的以__開始和結尾的函數&#xff0c;利用它們可以完成很多復雜的邏輯代碼&#xff0c;而且提高了代碼的簡潔性&#xff0c;本文主…

Silverlight 異步單元測試

Silverlight 中的很多操作都是異步的&#xff0c;很多情況下要求單元測試也是異步的&#xff0c;但是介紹異步單元測試的文檔很少。通過對 Silverlight Toolkit 中的 Microsoft.Silverlight.Testing 和 Microsoft.VisualStudio.QualityTools.UnitTesting.Silverlight 這兩個文件…

網絡拓撲 令牌環網 以太網_以太網連接中網絡拓撲的類型及其框架 以太網技術...

網絡拓撲 令牌環網 以太網A topology explains how physically the network is designed or what is the structure of the network. These designs are both physical and logical. There are many network topologies 4 like Bus, Star, Ring, and Mesh. But only two types …

Wafer晶圓封裝工藝介紹

芯片封裝的目的&#xff08;The purpose of chip packaging&#xff09;: 芯片上的IC管芯被切割以進行管芯間連接&#xff0c;通過引線鍵合連接外部引腳&#xff0c;然后進行成型&#xff0c;以保護電子封裝器件免受環境污染&#xff08;水分、溫度、污染物等&#xff09;&…

[轉載] Python中的解析式和生成器表達式

參考鏈接&#xff1a; Python | 生成器表達式 解析式和生成器表達式 列表解析List Comprehension 語法 [返回值 for 元素 in 可迭代對象 if 條件]使用中括號[],內部是for循環&#xff0c;if條件語句可選&#xff0c;會返回一個新的列表 列表解析試優點 編譯器會優化&…