1. 程式人生 > >pyhton (for in if)用法

pyhton (for in if)用法

高階語法

除了像上面介紹的 [x ** 2 for x in L] 這種基本語法之外,列表推導式還有一些高階的擴充套件。

4.1. 帶有if語句

我們可以在 for 語句後面跟上一個 if 判斷語句,用於過濾掉那些不滿足條件的結果項。

例如,我想去除列表中所有的偶數項,保留奇數項,可以這麼寫:

>>> L = [1, 2, 3, 4, 5, 6]
>>> L = [x for x in L if x % 2 != 0]
>>> L
[1, 3, 5]

4.2. 帶有for巢狀

在複雜一點的列表推導式中,可以巢狀有多個 for 語句。按照從左至右的順序,分別是外層迴圈到內層迴圈。

例如:

>>> [x + y for x in 'ab' for y in 'jk']
['aj', 'ak', 'bj', 'bk']

4.3. 既有if語句又有for巢狀

列表推導式可以帶任意數量的巢狀 for 迴圈,並且每一個 for 迴圈後面都有可選的 if 語句。

通用語法:

[ expression for x in X [if condition]
             for y in Y [if condition]
             ...
             for n in N [if condition] ]

例如,下面的程式碼輸出了0~4之間的偶數和奇數的組合。

>>> [(x, y) for x in range(5) if x % 2 == 0 for y in range(5) if y % 2 == 1]
[(0, 1), (0, 3), (2, 1), (2, 3), (4, 1), (4, 3)]

等價於下面的一般 for 迴圈:

>>> L = []
>>> for x in range(5):
...     if x % 2 == 0:
...         for y in range(5):
...             if y % 2 == 1:
...                 L.append((x, y))
>>> L
[(0, 1), (0, 3), (2, 1), (2, 3), (4, 1), (4, 3)]

4.4. 列表推導式生成矩陣

生成矩陣的方式有多種,例如手動賦值、一般for迴圈,還有就是列表推導式。如果我們要用列表推導式生成下面的矩陣,可以怎麼寫?

>>> M = [[1, 2, 3],
... [4, 5, 6],
... [7, 8, 9]]

一種方法是:

>>> M = [[x, x+1, x+2] for x in [1, 4, 7]]
>>> M
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]

矩陣的列數少時可以使用這種方法。

如果矩陣的列數較多,我們可以使用另外一種方式:在迴圈變數的表示式中使用列表推導式。

具體程式碼如下:

>>> M = [[y for y in range(x, x+3)] for x in [1, 4, 7]]
>>> M
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]

與之前帶 for 巢狀的語法不同,這個例子中,實際使用的是最基本的 [expression for x in L] 語法,只有一個 for 語句。

複雜的地方在於前面的變量表達式 expression 不再是簡單的變數運算,而是一個列表推導式,在這個例子中就是 [y for y in range(x, x+3)] 。
內層的列表推導式返回一個行向量,而這些行向量經由外層的列表推導式,最終形成一個二維列表,也就是我們想要的矩陣。

當然,在實際的應用中不能單純追求程式碼的簡潔,還要考慮到程式碼的可讀性和維護成本。
如果程式碼變得過於複雜,不易於理解,我們寧可多寫幾行程式碼來增加它的可讀性。

5. 生成器表示式

生成器表示式與列表推導式的語法相同,區別在於生成器表示式的外面使用圓括號,而列表推導式使用方括號。

6. 集合推導式和字典推導式

注意:集合推導式和字典推導式只有在Python2.7以及之後的版本中才有,Python2.7之前的版本不支援這兩種推導式。

集合推導式的語法與列表推導式相同,只需要把外面的方括號改成花括號即可。

例如,我們可以通過以下方式來生成一個集合:

>>> {x ** 2 for x in [1, 2, 2]}
{1, 4}

字典推導式的外面也是使用花括號,不過花括號的內部需要包含鍵值兩部分。

在值不重複的情況下,我們可以通過字典推導式快速交換鍵值對:

>>> D = {'a':1, 'b':2, 'c':3}
>>> D = {value: key for key, value in D.items()}
>>> D
{1: 'a', 2: 'b', 3: 'c'}
lix = [];
for x in range(1, 101):
    lix.push(x ** 2)
執行結果:lix = [1,4,9,16,25.....]

在列表構建器的表示式中,可以新增簡單的條件處理

lix = [x * x for x in range(1, 101) if x % 2 == 0]
執行結果:lix = [4,16,36.....]

也可以在迴圈過程中,來使用多層迴圈巢狀,實現更加複雜的效果

lix = [x + y  for x in "abc" for y in "xyz"]
執行結果:['ax', 'ay', 'az', 'bx', 'by', 'bz', 'cx', 'cy', 'cz']

列表動態構建器

但是我們通過前面的學習已經知道,這些資料都是載入到記憶體中的,如果列表中的資料量比較大的情況下,記憶體消耗是比較嚴重的
在某些情況下,我們只需要使用列表中的一部分資料,後面的資料並不是特別關心,如:通過列表來記錄一個符合某種規則的序列,每次我們只是關心下一個資料,並不關心後面的N條資料,應該怎麼做呢?比如我們需要一個奇數列表

# 常規構建器的做法
lix = [2*x + 1 for x in range(1, 101)]
# 執行結果:[1,3,5,7,9,11,13,15,17.....]
# * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
# 常規構建器可以直接構建生成
# 但是存在問題,如果一次構建的資料量太大,會嚴重佔用記憶體
# 我們在使用該列表的時候,有可能只是使用前10項
# * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
# 使用列表動態構建器
lix = (2 * x - 1 for x in range(1, 101))
# 執行結果:print (lix) --> <generator object <genexpr> at 0x7f232e462048>
next(lix)
# 執行結果:1
next(lix)
# 執行結果:3
next(lix)
# 執行結果:5
next(lix)
# 執行結果:7
# * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
# 列表動態構建器
# 和構建器基本沒有區別,建立的時候列表中是沒有資料的
# 必須通過next()函式來獲取列表中的下一條資料
# * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *


from:https://www.jianshu.com/p/fa3fda487f15

[]改成(),就建立了一個generator:

>>> L = [x * x for x in range(10)]
>>> L
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
>>> g = (x * x for x in range(10))
>>> g
<generator object <genexpr> at 0x1022ef630>

L和g的區別僅在於最外層的[]()L是一個list,而g是一個generator。

如果要一個一個打印出來,可以通過next()函式獲得generator的下一個返回值:

>>> next(g)
0
>>> next(g)
1
>>> next(g)
4
>>> next(g)
9
>>> next(g)

next(g)實在是太變態了,正確的方法是使用for迴圈,因為generator也是可迭代物件:

>>> g = (x * x for x in range(10))
>>> for n in g:
...     print(n)
... 
0
1
4
9
要把fib函式變成generator,只需要把print(b)改為yield b就可以了:
def fib(max):
    n, a, b = 0, 0, 1
    while n < max:
        yield b
        a, b = b, a + b
        n = n + 1
    return 'done'

yield關鍵字,那麼這個函式就不再是一個普通函式,而是一個generator:

>>> f = fib(6)
>>> f
<generator object fib at 0x104feaaa0>

return語句或者最後一行函式語句就返回。而變成generator的函式,在每次呼叫next()的時候執行,遇到yield語句返回,再次執行時從上次返回的yield語句處繼續執行。