1. 程式人生 > >Python專題——詳解enumerate和zip

Python專題——詳解enumerate和zip

本文始發於個人公眾號:TechFlow,原創不易,求個關注


今天是Python專題的第7篇文章,我們繼續介紹迭代相關。

enumerate

首先介紹的是enumerate函式。

在我們日常程式設計的過程當中,經常會遇到一個問題。

在C語言以及一些古老的語言當中是沒有迭代器這個概念的,所以我們要遍歷陣列或者是容器的時候,往往只能通過下標。有了迭代器之後,我們遍歷的過程方便了很多,我們可以直接用一個變數去迭代一個容器當中的值。最簡單的例子就是陣列的遍歷,比如我們要遍歷items這個陣列。我們可以直接:

for item in items:

通過迭代器的方式我們可以很輕鬆地遍歷陣列,而不再需要下標,也不需要計算陣列的長度了。但是如果我們在迴圈體當中需要知道元素的下標該怎麼辦?

難道我們真的只能在下標和迭代器當中選擇一個嗎,比如在迴圈體的外面新增一個變數來記錄下標?

idx = 0
for item in items:
operation()
idx += 1

這樣可以解決問題,但是很麻煩,一點也不簡潔,用專業的話來說一點也不pythonic(符合Python標準的程式碼)。為了追求pythonic,於是有了enumerate函式,來解決了我們又想直接迭代又需要知道元素下標的情形。

它的用法也很簡單,我們把需要迭代的物件或者迭代器傳入enumerate函式當中,它會為我們建立一個新的迭代器,同時返回下標以及迭代的內容。我們來看一個例子:

for i, item in enumerate(items):

除此之外,enumerate還支援傳入引數。比如在某些場景當中,我們希望下標從1開始,而不再是0開始,我們可以額外多傳入一個引數實現這點:

for i, item in enumerate(items, 1):

迴圈是我們程式設計的時候必不可少的操作,也正因此,enumerate函式使用非常廣泛。但是有一點需要注意,如果我們迭代的是一個多元組陣列,我們需要注意要將index和value區分開。舉個例子:

data = [(1, 3), (2, 1), (3, 3)]

在不用enumerate的時候,我們有兩種迭代方式,這兩種都可以執行。

for x, y in data:

for (x, y) in data:

但是如果我們使用enumerate的話,由於引入了一個index,我們必須要做區分,否則會報錯,所以我們只有一種迭代方式:

for i, (x, y) in enumerate(data):

zip

接下來要介紹的另一個函式同樣是方便我們迭代的,不過它針對的是另一個場景——多物件迭代。

它的應用場景非常簡單,就是我們想要同時迭代多份資料,比如使用者的名字和使用者的職業資料是分開的,我們希望同時遍歷一個使用者的職業和名字。如果不使用zip,我們可能只能放棄迭代器回到傳統的下標遍歷的模式了。這樣當然是可以的,不過有兩個小問題,第一個小問題當然是程式碼的可讀性變差了,不夠pythonic,第二個問題是我們需要維護兩個容器長度不一樣的情況,會增加額外的程式碼。而使用zip,可以同時解決以上兩個問題。

我們來看一個例子:

names = ['xiaoming', 'xiaohua', 'xiaohei', 'xiaoli']
jobs = ['coach', 'student', 'student', 'student', 'professor']

for name, job in zip(names, jobs):
print(name, job)

最後輸出的結果是人名和職業的tuple:

xiaoming coach
xiaohua student
xiaohei student
xiaoli student

上面舉的例子當中,names和jobs的長度其實是不一致的,在使用了zip的情況下,會自動替我們按照其中較短的那個進行截斷。如果我們不希望截斷,我們也可以使用itertools下的zip_longest來代替zip:

from itertools import zip_longest
for name, job in zip_longest(names, jobs):

這樣的話長度不夠的元素會以None來填充,zip_longest提供了一個引數fillvalue,可以填充成我們指定的值。

無論是zip還是zip_longest,都可以支援多迭代器的遍歷。比如:

names = ['xiaoming', 'xiaohua', 'xiaohei', 'xiaoli']
jobs = ['coach', 'student', 'student', 'student', 'professor']
hobbies = ['footbal', 'tennis', 'badminton', 'basketbal']

for name, job, hobby in zip(names, jobs, hobbies):
print(name, job, hobby)

zip除了方便我們迭代遍歷之外,另一個很大的用處是可以很方便地生成dict。比如剛才的例子當中,我們想生成一個名稱和職業的dict,一般的辦法當然是先定義一個dict,然後遍歷所有的key和value,來生成dict。然而使用zip,我們可以將這個操作簡化到一行程式碼:

jobDict = dict(zip(names, jobs))

需要注意的是,我們呼叫zip返回的結果其實是一個迭代器,我們在轉化成dict的時候自動遍歷了迭代器當中的內容。比如我們如果直接打印出zip呼叫結果的話,就會發現螢幕上輸出的是一個迭代器的地址:

print(zip(names, jobs))
>>> <zip object at 0x10ec93b40>

我們想要獲得它的內容,需要將它手動轉成list:

print(list(zip(names, jobs)))
>>> [('xiaoming', 'coach'), ('xiaohua', 'student'), ('xiaohei', 'student'), ('xiaoli', 'student')]

無論是enumerate還是zip其實底層都是基於迭代器實現的,從原理上來說並沒有什麼太深奧的內容,而且我們不使用它們也不影響我們寫程式碼。但是Python之所以是Python,之所以很多人稱道它簡潔的語言和邏輯,離不開我們廣泛地使用這些簡化程式碼邏輯的工具和方法。因此我們加以瞭解是非常有必要的,希望大家都能寫出pythonic的程式碼,不僅寫程式碼能力強,而且程式碼本身也漂亮。

今天的文章就是這些,如果覺得有所收穫,請順手點個關注或者轉發吧,你們的舉手之勞對我來說很重要。

相關推薦

Python專題——enumeratezip

本文始發於個人公眾號:TechFlow,原創不易,求個關注 今天是Python專題的第7篇文章,我們繼續介紹迭代相關。 enumerate 首先介紹的是enumerate函式。 在我們日常程式設計的過程當中,經常會遇到一個問題。 在C語言以及一些古老的語言當中是沒有迭代器這個概念的,所以我們要遍歷陣列或者是

LeetCode專題——搜尋演算法中的搜尋策略剪枝

本文始發於個人公眾號:**TechFlow**,原創不易,求個關注 今天是LeetCode專題第20篇文章,今天討論的是數字組合問題。 描述 給定一個int型別的候選集,和一個int型別的target,要求返回所有的數字組合,使得組合內所有數字的和剛好等於target。 注意: 所有的元素都是正數所有

httphttps的作用與區別

就是 免費證書 構建 難題 原理 過程 完全 mod 支持 PS: https就是http和TCP之間有一層SSL層,這一層的實際作用是防止釣魚和加密。防止釣魚通過網站的證書,網站必須有CA證書,證書類似於一個解密的簽名。另外是加密,加密需要一個密鑰交換算法,雙方通過交換後

【TP3.2】_initialize() __construct() 的區別聯系

instance ins 執行 構造方法 ces 實例化 direct control 初始化 1、假設 一個AdminController.class.php 集成至 \Think\Controller 類, 我們來看看Controller.class.php的構造方法源

sql優化專題

AC 頻繁 === 數據表 任務 對數 在那 first ack 數據庫的優化問題 一、問題的提出  在應用系統開發初期,由於開發數據庫數據比較少,對於查詢SQL語句,復雜視圖的的編寫等體會不出SQL語句各種寫法的性能優劣,但是如果將應用 系統提交實際應用後,隨著數據庫

python--“re”

industry 等等 trie 大寫字母 反向 情況下 lar 限制 獲取 一、什麽是正則表達式? 正則表達式(regular expression)描述了一種字符串匹配的模式,可以用來檢查一個串是否含有某種子串、將匹配的子串做替換或者從某個串中取出符合某個條件的子串等。

Python open

內容 lin bsp 二進制 truncate enc cat windows Coding 一、打開文件的模式有:   1、r,只讀模式【默認】。   2、w,只寫模式。【不可讀,不存在則創建,存在則刪除內容】   3、a,追加模式。【可讀,不存在則創建,存在則只追加內容

pathclasspath的區別

1.7 找到 index 配置 的區別 jdk1.7 修改 jdk1.6 應用 詳解path和classpath的區別 path的作用 path是系統用來指定可執行文件的完整路徑,即使不在path中設置JDK的路徑也可執行JAVA文件,但必須把完整的路徑寫出來,如

AddressRFC 822

                               詳解Address和RFC 822   名稱解釋

PyInstaller打包Python程式

PyInstaller可以將Python程式及其依賴項打包到一個包中,使用者可以在不安裝Python直譯器或任何模組的情況下執行打包的可執行程式,PyInstaller已經支援Python2.7和3.3+,可以構建多平臺的應用程式,在Windows平臺中建立可執行的Windows應用程式

C++STL之Vector向量,用法例子 一起學習 一起加油

                                            &

Spring boot 配置檔案 (properties yml )

從其他框架來看 我們都有自己的配置檔案, hibernate有hbm,mybatis 有properties, 同樣, Spring boot 也有全域性配置檔案。 Springboot使用一個全域性的配置檔案,而且配置檔案的名字是固定的。 有兩種 application.properties

Tiniux 3.0 Memory.c -- OSMemMalloc OSMemCalloc

--------------------------------------------- -- 時間:2018-11-13 -- 建立人:Ruo_Xiao -- 郵箱:[email protected] -- 若大神不吝拋磚,小菜感激不盡! ---------------------

[JavaMail] MultipartBody

轉: http://blog.itpub.net/15182208/viewspace-730172/   A、簡介   Message表示一個郵件,messgaes.getContent()返回一個Multipart物件。一個Multipart物件包含

pythonpandas.DataFrame.plot( ) 中引數secondary_y實現雙座標軸使用

首先看官網的DataFrame.plot( )函式 secondary_y : boolean or sequence, default False # 可以是布林值或者是數列 Whether to plot on the secondary y-axis

python事件驅動event實現

所有的計算機程式都可以大致分為兩類:指令碼型(單次執行)和連續執行型(直到使用者主動退出)。 指令碼型:指令碼型的程式包括最早的批處理檔案以及使用Python做交易策略回測等等,這類程式的特點是在使用者啟動後會按照程式設計時設計好的步驟一步步執行,所有步驟執行完後自動退出。

pythonqueue佇列

一、佇列的定義 佇列類似於一條管道,元素先進先出,進put(arg),取get( )。需要注意的是:佇列都是在記憶體中操作,程序退出,佇列清空,另外,佇列也是一個阻塞的形態。 二、佇列分類 佇列有很多種,但都依賴模組queue 佇列方式

pythoncollections模組中OrderedDict的使用

很多人認為python中的字典是無序的,因為它是按照hash來儲存的,但是python中有個模組collections(英文,收集、集合),裡面自帶了一個子類OrderedDict,實現了對字典物件中元素的排序。 import collections print("Regular d

pythonisinstance方法

isinstance() 函式來判斷一個物件是否是一個已知的型別,類似 type()。 isinstance() 與 type() 區別: type() 不會認為子類是一種父類型別,不考慮繼承關係。 isinstance() 會認為子類是一種父類型別,考慮繼承

pythonpandas庫的pd.merge_ordered與pd.merge_asof

merge_ordered: 函式允許組合時間序列和其他有序資料。 特別是它有一個可選的fill_method關鍵字來填充/插入缺失的資料。 import pandas as pd left = pd.DataFrame({'k': ['K0', 'K1', 'K1'