使用列表、字典和集合生成式來縮短代碼

做者|Philip Wilkinson
編譯|VK
來源|Towards Datas Sciencepython

在使用Python將近一年的時間裏,我常常遇到「生成式」這個詞,但我沒生成式它的確切含義或它所涵蓋的內容。編程

直到最近,我才發現,有了生成式後,我能夠利用列表將個人代碼從多行縮短爲一行。此外,這種代碼縮短方法不只能夠用於列表,還能夠用於字典和集合。app

本文試圖解釋生成式在列表、字典和集合的適用性,以及它們如何減小平常編程所需的代碼量。dom

首先,生成式是能夠在一行中建立列表、字典和集合的代碼片斷。這樣就沒必要爲for循環使用多行,並且還減小了使用map()、filter()和reduce()函數的須要。機器學習

它們由方括號(根據你要建立的數據類型而定)組成,其中包含一個表達式,後跟一個for子句和一個或多個if子句。表達式自己能夠是任何東西,這意味着你能夠將許多不一樣的對象放入列表中,只要它們是可編輯的。所以,從減小使用的行數和增長可讀性的角度來探討這些可能對代碼產生的影響是值得的。函數

列表

在python中,只需將項目放在方括號([])內,用逗號分隔,就能夠建立列表,以下所示。學習

list1 = [1, 2, 3, "hello", 7.0, 52]

它們一般用於多種目的的編程中,但在長格式中編寫或使用for循環進行編輯都會很麻煩。首先,在建立列表方面,小列表可能很容易以長格式打印出來,例如:ui

nums = [1, 2, 3, 4, 5, 6, 7, 8]

但當這個值變長時,即在0-50範圍內,甚至更長,它們可能會變得笨重。它們能夠經過for循環使用range函數輕鬆建立,以下所示:.net

nums = []

for i in range(1, 51):
    nums.append(i)

print(nums)

# out: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50]

可是咱們可使用列表生成式將其縮短爲一行,而且不須要append()方法。code

nums = [i for i in range(1,51)]

print(nums)

# out: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50]

基本上,for循環放在一行中,同時初始化列表,從上面的示例中消除了對第一行和第二行代碼的須要。

當咱們開始爲添加到列表中的數字添加條件時,這就變得更加劇要了,好比只容許偶數而且但願這些數字是平方的。一樣,也可使用for循環生成,以下所示:

square_nums = []

for x in range(1,26):
    if x % 2 == 0:
        square_nums.append(x**2)

print(square_nums)

# out: [4, 16, 36, 64, 100, 144, 196, 256, 324, 400, 484, 576]

可是,一樣可使用列表生成式將其縮短爲一行,從而減小對用於在範圍內循環、建立條件並將結果附加到原始列表的行的須要。

square_nums = [x**2 for x in range(1,26) if x % 2 == 0]

print(square_nums)

#out: [4, 16, 36, 64, 100, 144, 196, 256, 324, 400, 484, 576]

在這裏,數字的轉換在行首執行x**2,for循環在行中執行,對於x在範圍(1,26),條件在末尾執行,就好像x%2==0同樣。這本質上使代碼更具可讀性,由於全部操做都在一行中執行,並減小了生成相同輸出所需的代碼量。

這還能夠減小append()、map()、filter()或reduce()方法在建立新列表時對現有列表進行操做的須要,再次下降代碼的複雜性並使其更具可讀性。

相似的例子是很容易得到的,更多的信息能夠很容易地經過其餘文章在媒介,如這裏和這裏得到。然而,值得注意的是,這些生成式也能夠用於字典和集合。

字典

字典是一個無序的數據集合,能夠改變和索引,使用大括號和鍵和值對編寫。在這裏,鍵被用來訪問值,而且常常被用來存儲信息,這些信息對這些信息是有用的。下面提供了一個示例,例如用於存儲分數。

Grades = {
    "Steven": 57,
    "Jessica": 82,
    "William": 42,
    "Hussein": 78,
    "Mary": 65,
    }
    
print(Grades)

# out: {'Steven': 57, 'Jessica': 82, 'William': 42, 'Hussein': 78, 'Mary': 65}

與列表相似,有時也會很耗時,所以可使用for循環和條件語句來構造,但能夠更簡單地使用生成式來構造。

例如,對於咱們在上面建立的列表,咱們不只想知道數字的平方,並且還想存儲原始數字,這樣咱們就可使用它輕鬆地查找它的平方值。而後,咱們能夠簡單地建立一個包含鍵值對的字典,其中key表明原始數字,value表明數字的平方。使用for循環:

#初始化空dict
even_squared_dict = {}

for x in range(1,10):
    if x % 2 == 0:
        even_squared_dict[x] = x**2

print(even_squared_dict)

# out: {2: 4, 4: 16, 6: 36, 8: 64}

可是使用字典生成式:

even_sqaured_dict = {x: x**2 for x in range(1,10) if x % 2 ==0}

print(even_squared_dict)

# out: {2: 4, 4: 16, 6: 36, 8: 64}

本質上,這個和列表生成式之間的惟一區別是使用大括號來包含生成式,並將x放在冒號前面,以指示這表示鍵。

而後,還可使用它來建立基於現有列表的字典。例以下面,字典生成式用於建立一個字典,其鍵爲三位數的國家代碼,值爲兩位數的國家代碼,其中兩位數代碼與三位數代碼的前兩位數相同。

ThreeCharCodes = ["CAN", "FIN", "FRA", "GAB", "HKG", "IMN",
                  "MCO", "NPL"]
                  
cntryDict = {c: c[:2] for c in threeCharCodes}

print(cntryDict)

# out: {'CAN': 'CA', 'FIN': 'FI', 'FRA': 'FR', 'GAB': 'GA', 'HKG': 'HK', 'IMN': 'IM', 'MCO': 'MC', 'NPL': 'NP'}

集合

最後,生成式也能夠用於建立集合,集合是一種不一樣於列表或元組的數據類型,不能存儲同一元素的屢次出現。

在這樣作時,它存儲無序值,初始化方法是將一個列表傳遞給set()或使用大括號來包含由逗號分隔的值(儘管空的花括號將初始化字典)。下面提供了一個例子:

Fruits1 = set(["apple", "banana", "cherry", "apple"])
print(Fruits1)

Fruits2 = {"orange", "pear", "grape", "pear"}
print(Fruits2)

# out: {'apple', 'cherry', 'banana'}
       {'grape', 'pear', 'orange'}

從這裏能夠清楚地看到,儘管向集合傳遞了多個apple或pear值,但只生成了一個實例。一樣,可使用for循環生成這些命令,以下所示:

import random

nums = set([])

for x in range(25):
    y = random.randint(10,20)
    nums.add(y)

print(nums)

# out: {10, 12, 14, 15, 16, 17, 18, 20}

雖然25個隨機整數在10-20之間,但最終輸出僅包含8個惟一值,而不是列表中出現的25個值。一樣,使用對集合的生成式能夠更簡潔地編寫這篇文章。

nums = {random.randint(10,20) for num in range(25)}

print(nums)

# out: {11, 12, 13, 14, 15, 16, 17, 19, 20}

所以,這種生成式與列表生成式的區別在於使用大括號,而不是包含生成式的方括號。

與列表和字典生成式相似,這也能夠用於現有列表以生成集合。例如,若是咱們想根據1.6的除法將千米改成英里,只須要惟一的值,並將其限制爲小於100千米的值。

kms = [10, 12, 65, 40, 12, 75, 34, 65, 10, 10, 38, 100, 160, 200]

miles = {d/1.6 for d in kms if d < 100}

print(miles)

# out: {0.625, 0.75, 2.5, 2.125, 4.0625, 4.6875, 2.375}

總結

所以,生成式能夠很容易地用於建立新的列表、詞典和集合。使用這些能夠減小生成它們所需的行數,並提升可讀性。它們能夠用做append()、map()、filter()或reduce()函數的替換。

顯然,能夠將它們放大以執行更復雜的生成式,例如使用lambda函數、嵌套列表生成式或多條件語句。然而,在這樣作時值得注意的是,生成式可能很快變得難以理解,在這種狀況下,值得回到建立函數或for循環,以便在須要執行多個操做時提升可讀性。

原文連接:https://towardsdatascience.co...

歡迎關注磐創AI博客站:
http://panchuang.net/

sklearn機器學習中文官方文檔:
http://sklearn123.com/

歡迎關注磐創博客資源彙總站:
http://docs.panchuang.net/

相關文章
相關標籤/搜索