翻譯:《實用的Python編程》02_06_List_comprehension

目錄 | 上一節 (2.5 collections模塊) | 下一節 (2.7 對象模型)html

2.6 列表推導式

一個常見的任務是處理列表中的項(譯註:元素)。本節介紹列表推導式,完成此任務的強大工具。python

建立新列表

列表推導式經過將操做應用於序列的每個元素來建立新列表。git

>>> a = [1, 2, 3, 4, 5]
>>> b = [2*x for x in a ]
>>> b
[2, 4, 6, 8, 10]
>>>

再如:程序員

>>> names = ['Elwood', 'Jake']
>>> a = [name.lower() for name in names]
>>> a
['elwood', 'jake']
>>>

列表推導式的通常語法是:[ <expression> for <variable_name> in <sequence> ]github

過濾

也能夠在列表推導式中對元素進行過濾。數據庫

>>> a = [1, -5, 4, 2, -2, 10]
>>> b = [2*x for x in a if x > 0 ]
>>> b
[2, 8, 4, 20]
>>>

用例

列表推導式超級有用。例如,能夠收集特定字典字段的值:express

stocknames = [s['name'] for s in stocks]

在序列上執行類數據庫查詢:bash

a = [s for s in stocks if s['price'] > 100 and s['shares'] > 50 ]

也能夠把列表推導式與序列縮減合併在一塊兒:app

cost = sum([s['shares']*s['price'] for s in stocks])

通常語法

[ <expression> for <variable_name> in <sequence> if <condition>]

上面語法的含義:函數

result = []
for variable_name in sequence:
    if condition:
        result.append(expression)

歷史題外話

列表推導式來自於數學(集合構建符號)。

a = [ x * x for x in s if x > 0 ] # Python

a = { x^2 | x ∈ s, x > 0 }         # Math

這在其它幾種語言中也實現了,雖然大部分的程序員可能已經想不起他們的數學課了。因此,能夠將其視爲很酷的列表快捷方式。

練習

首先運行 report.py 程序,以便可以在交互模式下中加載股票投資組合。

bash % python3 -i report.py

如今,在 Python 交互提示符下,輸入語句以執行下述操做。這些操做對投資組合數據執行各種縮減,轉換和查找。

練習 2.19:列表推導式

嘗試一些簡單的列表推導式來熟悉語法:

>>> nums = [1,2,3,4]
>>> squares = [ x * x for x in nums ]
>>> squares
[1, 4, 9, 16]
>>> twice = [ 2 * x for x in nums if x > 2 ]
>>> twice
[6, 8]
>>>

請注意列表推導式是如何經過適當轉換或過濾的數據建立一個新列表的。

練習 2.20:序列縮減

使用單個 Python 語句計算投資組合的總價。

>>> portfolio = read_portfolio('Data/portfolio.csv')
>>> cost = sum([ s['shares'] * s['price'] for s in portfolio ])
>>> cost
44671.15
>>>

完成後,展現如何使用單個語句計算投資組合的當前值。

>>> value = sum([ s['shares'] * prices[s['name']] for s in portfolio ])
>>> value
28686.1
>>>

上面的兩個操做都是映射縮減的列子。列表推導式將操做映射到整個列表。

>>> [ s['shares'] * s['price'] for s in portfolio ]
[3220.0000000000005, 4555.0, 12516.0, 10246.0, 3835.1499999999996, 3254.9999999999995, 7044.0]
>>>

而後,sum() 函數對全部結果進行縮減。

>>> sum(_)
44671.15
>>>

有了這些知識,你如今就能夠準備成立一家大數據創業公司了。

練習 2.21:數據查詢

請嘗試如下各類數據查詢示例。

首選是建立一個列表,存儲持有 100 股以上的股票投資組合。

>>> more100 = [ s for s in portfolio if s['shares'] > 100 ]
>>> more100
[{'price': 83.44, 'name': 'CAT', 'shares': 150}, {'price': 51.23, 'name': 'MSFT', 'shares': 200}]
>>>

持有 MSFT 和 IBM 股票的全部投資組合。

>>> msftibm = [ s for s in portfolio if s['name'] in {'MSFT','IBM'} ]
>>> msftibm
[{'price': 91.1, 'name': 'IBM', 'shares': 50}, {'price': 51.23, 'name': 'MSFT', 'shares': 200},
  {'price': 65.1, 'name': 'MSFT', 'shares': 50}, {'price': 70.44, 'name': 'IBM', 'shares': 100}]
>>>

持有總價超過 $10000 的全部股票投資組合。

>>> cost10k = [ s for s in portfolio if s['shares'] * s['price'] > 10000 ]
>>> cost10k
[{'price': 83.44, 'name': 'CAT', 'shares': 150}, {'price': 51.23, 'name': 'MSFT', 'shares': 200}]
>>>

練習 2.22:數據提取

展現如何構建元組 (name, shares) 列表,名稱(name )和 股數(shares)從股票投資組合(portfolio)中獲取:

>>> name_shares =[ (s['name'], s['shares']) for s in portfolio ]
>>> name_shares
[('AA', 100), ('IBM', 50), ('CAT', 150), ('MSFT', 200), ('GE', 95), ('MSFT', 50), ('IBM', 100)]
>>>

若是將方括號([,])更改成花括號({, }),那麼將獲得集合推導式。這會獲得獨一無二的的或無重複的值。

例如,這將肯定集合中的股票名稱是獨一無二的:

>>> names = { s['name'] for s in portfolio }
>>> names
{ 'AA', 'GE', 'IBM', 'MSFT', 'CAT' }
>>>

若是指定鍵值對(key:value),則能夠構建一個字典。例如,構建一個將股票名稱映射到持有的股票數量的字典:

>>> holdings = { name: 0 for name in names }
>>> holdings
{'AA': 0, 'GE': 0, 'IBM': 0, 'MSFT': 0, 'CAT': 0}
>>>

後面的特性就是衆所皆知的字典推導式。讓咱們將其表格化:

>>> for s in portfolio:
        holdings[s['name']] += s['shares']

>>> holdings
{ 'AA': 100, 'GE': 95, 'IBM': 150, 'MSFT':250, 'CAT': 150 }
>>>

請嘗試如下示例,該示例將 prices 字典過濾出僅在 portfolio 中出現的名稱(name):

>>> portfolio_prices = { name: prices[name] for name in names }
>>> portfolio_prices
{'AA': 9.22, 'GE': 13.48, 'IBM': 106.28, 'MSFT': 20.89, 'CAT': 35.46}
>>>

練習 2.23: 從 CSV 文件提取數據

在各種數據處理中,知道如何將列表,集合,字典推導式聯合使用會很是有用。這裏有一個示例,展現如何從 CSV 文件中提取所選擇的列。

首先,從 CSV 文件讀取一行標題信息:

>>> import csv
>>> f = open('Data/portfoliodate.csv')
>>> rows = csv.reader(f)
>>> headers = next(rows)
>>> headers
['name', 'date', 'time', 'shares', 'price']
>>>

接着,定義一個變量列出實際須要的列:

>>> select = ['name', 'shares', 'price']
>>>

如今,在 CSV 源文件中找到以上各列的索引。

>>> indices = [ headers.index(colname) for colname in select ]
>>> indices
[0, 3, 4]
>>>

最後,使用字典推導式讀取數據的一行並把其轉換爲字典。

>>> row = next(rows)
>>> record = { colname: row[index] for colname, index in zip(select, indices) }   # dict-comprehension
>>> record
{'price': '32.20', 'name': 'AA', 'shares': '100'}
>>>

若是你對前面的操做感到滿意,那麼請讀取文件的剩餘部分:

>>> portfolio = [ { colname: row[index] for colname, index in zip(select, indices) } for row in rows ]
>>> portfolio
[{'price': '91.10', 'name': 'IBM', 'shares': '50'}, {'price': '83.44', 'name': 'CAT', 'shares': '150'},
  {'price': '51.23', 'name': 'MSFT', 'shares': '200'}, {'price': '40.37', 'name': 'GE', 'shares': '95'},
  {'price': '65.10', 'name': 'MSFT', 'shares': '50'}, {'price': '70.44', 'name': 'IBM', 'shares': '100'}]
>>>

天啊,已經把 read_portfolio() 函數簡化爲單個語句了。

說明

列表推導式在 Python 中經常使用做轉換,過濾和收集數據的有效方法。因爲語法的緣由,請不要走極端——應該讓每一個列表推導式儘量簡單。能夠將事情分解爲多個步驟。例如,不清楚你會不會把最後一個例子強加給絕不知情的同事。

也就是說,知道如何快速處理數據是一項很是有用的技能。在不少狀況下,可能必須解決某種一次性的問題,包括數據導入,導出,提取等。成爲列表推導式的大師能夠大大減小設計方案所花費的時間。另外,不要忘記 collections 模塊。

目錄 | 上一節 (2.5 collections模塊) | 下一節 (2.7 對象模型)

注:完整翻譯見 https://github.com/codists/practical-python-zh

相關文章
相關標籤/搜索