Python 列表推導(dǎo)式需要注意的地方
原文地址:The Do's and Don'ts of Python List Comprehension
原文作者:Yong Cui, Ph.D.
譯文出自:掘金翻譯計劃
本文永久鏈接:github.com/xitu/gold-m…
譯者:samyu2000
校對者:luochen1992,shixi-li
Python 列表推導(dǎo)式并不是給初學(xué)者用的,因為它非常反直覺,甚至對于有其他編程語言背景的人也是如此。
我們接觸到 List 的使用時,學(xué)習(xí)的內(nèi)容都是零散的。所以我們?nèi)鄙僖粋€關(guān)于如何在各種各樣的場景下使用 List 的知識體系。
本文提供了一些 List 的使用指南,盡可能涵蓋各個方面。希望本文可以成為你的一站式實用手冊。
使用建議
1.建議使用迭代的方式
使用 List 最基本的方式是以一個可迭代對象為基礎(chǔ),創(chuàng)建一個 List 對象,這個可迭代對象可以是任意可以迭代元素的Python對象。使用方法如下。
[expression for item in iterable]
下面這段代碼展示了一個使用列表相關(guān)技術(shù)創(chuàng)建 List 對象的例子。在這個例子中,我們定義了一個 Integer 列表,并基于這個對象創(chuàng)建了保存每個數(shù)字的平方數(shù)和立方數(shù)的 List 對象。
>>> # 創(chuàng)建一個 Integer 列表 >>> integers = [1, 2, 3, 4, 5, 6] >>> # 創(chuàng)建平方數(shù)和立方數(shù)列表 >>> powers = [(x*x, pow(x, 3)) for x in integers] >>> print(powers) [(1, 1), (4, 8), (9, 27), (16, 64), (25, 125), (36, 216)]
上面的例子把 List 對象當(dāng)作迭代器使用。我們應(yīng)該知道,許多類型的對象也是可迭代的,比如 List、Set、Dictionary 和 String 等等。其他數(shù)據(jù)類型,像 range、map、filter,以及 pandas 包中的 Series、DataFrame,都是可迭代的。下面的代碼演示了某些對象的使用方法。
>>> # 使用 range 對象 >>> integer_range = range(5) >>> [x*x for x in integer_range] [0, 1, 4, 9, 16] >>> # 使用 Series 對象 >>> import pandas as pd >>> pd_series = pd.Series(range(5)) >>> print(pd_series) 0 0 1 1 2 2 3 3 4 4 dtype: int64 >>> [x*x for x in pd_series] [0, 1, 4, 9, 16]
2.如果只需用到其中的某些元素,應(yīng)當(dāng)使用條件判斷語句
假設(shè)你需要將符合某種條件的元素歸集起來,并創(chuàng)建一個 list。下面展示了相關(guān)的語法。
[expression for item in iterable if condition]
if 語句用來實現(xiàn)條件判斷。下面的代碼展示了這種用法的一個簡單示例。
>>> # 同樣創(chuàng)建一個 Integer 列表 >>> integers = [1, 2, 3, 4, 5, 6] >>> # 篩選出偶數(shù),創(chuàng)建一個這些偶數(shù)的平方數(shù)列表 >>> squares_of_evens = [x*x for x in integers if x % 2 == 0] >>> print((squares_of_evens)) [4, 16, 36]
3.使用條件判斷語句
List 對象中還可以使用 if-else 形式的條件判斷,語法如下。
[expression0 if condition else expression1 for item in iterable]
這跟前面的那種用法有些類似,別把這兩種用法混淆。在本例中,條件語句本身是一個整體。下面的代碼提供了一個例子。
>>> # 創(chuàng)建一個 Integer 列表 >>> integers = [1, 2, 3, 4, 5, 6] >>> # 遍歷 integers 中的元素,如果是偶數(shù),取平方數(shù)存入新的列表 >>> # 如果是奇數(shù),取立方數(shù)存入新的列表 >>> custom_powers = [x*x if x % 2 == 0 else pow(x, 3) for x in integers] >>> print(custom_powers) [1, 4, 27, 16, 125, 36]
4.如果有嵌套結(jié)構(gòu),可以使用嵌套的循環(huán)
有可能可迭代對象中的元素自身也是可迭代的,盡管這種情況不太常見。如果你對嵌套的可迭代對象有興趣,可以使用 for 來實現(xiàn)循環(huán)嵌套。語法如下。
[expression for item_outer in iterable for item_inner in item_outer] # 與下面的代碼等同 for item_outer in iterable: for item_inner in item_outer: expression
上面的代碼展示了使用for實現(xiàn)嵌套循環(huán)的例子。
>>> # 創(chuàng)建一個包含元組的列表 >>> prices = [('$5.99', '$4.99'), ('$3.5', '$4.5')] >>> # 獲取元組中的每個價格,以此創(chuàng)建一個一維列表 >>> prices_formatted = [float(x[1:]) for price_group in prices for x in price_group] >>> print(prices_formatted) [5.99, 4.99, 3.5, 4.5]
5.替換高階函數(shù)
有的人比較習(xí)慣函數(shù)式編程,比如使用高階函數(shù)也是這種習(xí)慣的表現(xiàn)之一。特別說明一下,高階函數(shù)是那些需要使用輸入或輸出參數(shù)的函數(shù)。在 Python 中,常用的高階函數(shù)有 map() 和 filter()。
>>> # 創(chuàng)建一個 integer 類型的列表 >>> integers = [1, 2, 3, 4, 5] >>> # 使用 map 創(chuàng)建平方數(shù)列表 >>> squares_mapped = list(map(lambda x: x*x, integers)) >>> squares_mapped [1, 4, 9, 16, 25] >>> # 使用列表推導(dǎo)式創(chuàng)建平方數(shù)列表 >>> squares_listcomp = [x*x for x in integers] >>> squares_listcomp [1, 4, 9, 16, 25] >>> # 使用 filter 取得 integers 中的偶數(shù)列表 >>> filtered_filter = list(filter(lambda x: x % 2 == 0, integers)) >>> filtered_filter [2, 4] >>> # 使用列表推導(dǎo)式取得 integers 中的偶數(shù)列表 >>> filterd_listcomp = [x for x in integers if x % 2 == 0] >>> filterd_listcomp [2, 4]
從上面的例子可以看出,使用 list 的某些特性比使用高階函數(shù)更具有可讀性,而且也能實現(xiàn)較復(fù)雜的嵌套結(jié)構(gòu)。
使用禁忌
1.不要忘了定義構(gòu)造函數(shù)
有人認(rèn)為列表推導(dǎo)式很酷炫,是 Python 特有的功能,所以為了炫耀自己的 Python 水平,即使有更好替代方案也要使用它。
>>> # 使用 range 創(chuàng)建列表對象 >>> numbers = [x for x in range(5)] >>> print(numbers) [0, 1, 2, 3, 4] >>> # 以一個字符串為基礎(chǔ),創(chuàng)建一個小寫字母的字符列表 >>> letters = [x.lower() for x in 'Smith'] >>> print(letters) ['s', 'm', 'i', 't', 'h']
上述例子中,我們使用了 range 和 string,這兩種數(shù)據(jù)結(jié)構(gòu)都是可迭代的,list()構(gòu)造函數(shù)可以直接使用 iterable 創(chuàng)建一個 list 對象。下面的代碼提供了更合理的解決方案。
>>> # 使用 range 創(chuàng)建列表對象 >>> numbers = list(range(5)) >>> print(numbers) [0, 1, 2, 3, 4] >>> # 以一個字符串為基礎(chǔ),創(chuàng)建一個小寫字母的字符列表 >>> letters = list('Smith'.lower()) >>> print(letters) ['s', 'm', 'i', 't', 'h']
2.不要忘了生成器表達(dá)式
在 Python 中,生成器是一種特殊的可迭代對象,它會延遲加載元素,直到被請求才會加載。這在處理大量數(shù)據(jù)時會非常高效,它能提升存儲效率。相比之下,list 對象為了方便計數(shù)和索引,一次性創(chuàng)建所有的元素。所以跟生成器相比,在元素個數(shù)相同時,list 需要占用更多內(nèi)存。
我們可以定義一個生成器函數(shù)來創(chuàng)建生成器。我們也可以使用下面的語句來創(chuàng)建生成器,這是一種稱為生成器表達(dá)式的方法。
(expression for item in iterable)
你可能會注意到,除了使用圓括號外,它的語法跟使用 list 的語句很相似。所以需要注意區(qū)分。
考慮下面這個例子。我們要計算前一百萬個數(shù)字的平方和。如果使用 list 來實現(xiàn),方法如下。
>>> # 創(chuàng)建列表對象 squares >>> squares = [x*x for x in range(10_000_000)] >>> # 計算它們的總和 >>> sum(squares) 333333283333335000000 >>> squares.__sizeof__() 81528032
跟使用 list 相比,使用 generator 內(nèi)存開銷小得多,只有 96 字節(jié)。原因很簡單———— generator 不需要獲取所有的元素。相反,它只需要獲取各個元素在序列中的位置,創(chuàng)建下一個元素并呈現(xiàn)它,而且不必保存在內(nèi)存中。
結(jié)論
本文中,我們整理了 list 應(yīng)用的一些關(guān)鍵要領(lǐng)。這些該做的和不該做的都非常清晰明了。我估計你會在合適的場景中用到它。下面是本文內(nèi)容的小結(jié)。
- 使用迭代的方式。 Python 中有許多類型的 iterable,你應(yīng)當(dāng)在掌握基礎(chǔ)(list 和 tuple)的同時融會貫通。
- 使用條件判斷語句。 如果你對在 iterable 中篩選某些元素感興趣,可以多多研究條件判斷。
- 使用條件判斷表達(dá)式。 如果你需要有選擇性地獲取某些數(shù)據(jù),可以使用條件判斷表達(dá)式。
- 使用嵌套的循環(huán)。 如果你要處理嵌套的 iterable,可以使用嵌套的循環(huán)結(jié)構(gòu)。
- 用 list 替代高階函數(shù) 在很多情況下,可以用 list 替代高階函數(shù)。
- 不要忘記 list 的構(gòu)造函數(shù) 定義 list 的構(gòu)造函數(shù),可以使用 iterable 創(chuàng)建一個 list 對象。如果你直接使用 iterable,推薦用這個方法。
- 不要忘了生成器表達(dá)式 它的語法與 list 中的語法相似。在處理大量的對象時,這是一種節(jié)省內(nèi)存開銷的辦法。list 和 generator 不同的是,為了日后的索引和訪問, list 必須提前創(chuàng)建,如果元素個數(shù)很多,就會消耗很大的內(nèi)存。
以上就是Python 列表推導(dǎo)式需要注意的地方的詳細(xì)內(nèi)容,更多關(guān)于Python 列表推導(dǎo)式的資料請關(guān)注腳本之家其它相關(guān)文章!
- Python之列表推導(dǎo)式最全匯總(上篇)
- Python之列表推導(dǎo)式最全匯總(中篇)
- python中列表推導(dǎo)式與生成器表達(dá)式對比詳解
- Python列表推導(dǎo)式,元組推導(dǎo)式,字典推導(dǎo)式,集合推導(dǎo)式
- Python的列表推導(dǎo)式你了解嗎
- python列表推導(dǎo)式的原理及使用方法
- python列表推導(dǎo)式實現(xiàn)找出列表中長度大于5的名字
- Python 列表推導(dǎo)式與字典推導(dǎo)式的實現(xiàn)
- Python列表推導(dǎo)式詳情
- python列表推導(dǎo)式 經(jīng)典代碼
- Python列表推導(dǎo)式實現(xiàn)代碼實例
- 什么是python的列表推導(dǎo)式
- python列表推導(dǎo)式入門學(xué)習(xí)解析
- python之列表推導(dǎo)式的用法
- python列表推導(dǎo)式操作解析
- python 列表推導(dǎo)式使用詳解
- 簡單了解python 生成器 列表推導(dǎo)式 生成器表達(dá)式
- Python之列表推導(dǎo)式最全匯總(下篇)
相關(guān)文章
關(guān)于numpy強(qiáng)制類型轉(zhuǎn)換的問題
這篇文章主要介紹了關(guān)于numpy強(qiáng)制類型轉(zhuǎn)換的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-05-05python和pywin32實現(xiàn)窗口查找、遍歷和點擊的示例代碼
這篇文章主要介紹了python和pywin32實現(xiàn)窗口查找、遍歷和點擊的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-04-04用TensorFlow實現(xiàn)lasso回歸和嶺回歸算法的示例
本篇文章主要介紹了用TensorFlow實現(xiàn)lasso回歸和嶺回歸算法的示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-05-05安裝pyhttpx解決ImportError: DLL load failed錯誤
這篇文章主要為大家介紹了安裝pyhttpx解決ImportError: DLL load failed錯誤,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-08-08一文帶你深入理解python中pytest-repeat插件的工作原理
這篇文章主要和大家一起深入探討到底pytest_repeat插件的具體功能是如何實現(xiàn)的呢,相信具體了解了該插件,其他三方插件也可以很快了解它內(nèi)部運行機(jī)制,所以本文詳細(xì)講解了python pytest-repeat插件的工作原理,需要的朋友可以參考下2023-09-09Python發(fā)起請求提示UnicodeEncodeError錯誤代碼解決方法
這篇文章主要介紹了Python發(fā)起請求提示UnicodeEncodeError錯誤代碼解決方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-04-04解決windows上安裝tensorflow時報錯,“DLL load failed: 找不到指定的模塊”的問題
這篇文章主要介紹了解決windows上安裝tensorflow時報錯,“DLL load failed: 找不到指定的模塊”的問題,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-05-05