python(15)列表推導式、生成器、迭代器

一、列表推導式

列表推導式、字典推導式、集合推導式

舊的列表 ——> 新的列表

1、列表推導式

格式:  [表達式 for 變量 in 舊列表]  或者  [表達式 for 變量 in 舊列表 if 條件]

#過濾掉長度小於等於3的姓名
names = ['aaa', 'bbbb', 'jack', 'abc']

result = [name for name in names if len(name) > 3]
print(result)

#將過濾的姓名首字母大寫
result = [name.capitalize() for name in names if len(name) > 3]
print(result)
'''
簡化了此過程
for name in names:
    newlist = []
    if len(name) > 3:
        name.title()
        newlist.append(name)
    return newlist
'''
#將1~100之間能被3整除,組成一個新的列表
newlist = [i for i in range(1, 101) if i % 3 == 0 and i % 5 == 0]#攜帶if條件
print(newlist)

#此處,類比三元表達式     條件爲真時的結果 if 條件 else 條件爲假時的結果
#         列表推導式     [表達式 for i in 列表 if 條件]

#[(偶數, 奇數), (), ()]  0~5的偶數  0~10的奇數
newlist = [(x, y) for x in range(5) if x % 2 == 0 for y in range(10) if y % 2 != 0]
print(newlist)
'''
def func():
    newlist = []
    for i in range(5):#偶數
        if i % 2 == 0:
            for j in range(10):
                if j % 2 != 0:
                    newlist.append((i, j))
    return newlist
result = func()
print(result)
'''
#list1 = [[1, 2, 3], [4, 5, 6], [7 ,8, 9], [1, 3, 5]] --->[3, 6, 9 ,5]
list1 = [[1, 2, 3], [4, 5, 6], [7 ,8, 9], [1, 3, 5]]
newlist = [i[-1] for i in list1]#沒有條件    #取每個列表中最後一個元素
print(newlist)

dict1 = {'name' : 'tom', 'salary' : 5000}
dict2 = {'name' : 'lucy', 'salary' : 8000}
dict3 = {'name' : 'jack', 'salary' : 4500}
dict4 = {'name' : 'lily', 'salary' : 3000}
list1 = [dict1, dict2, dict3, dict4]
#if 薪資大於 5000, 加200, 低於5000 加500
#if爲true執行語句 if 條件 else 執行語句 for 元素 in 列表
newlist = [person['salary'] + 200 if person['salary'] > 5000 else person['salary'] + 500 for person in list1]
print(newlist)

2、集合推導式  {}

集合去重且無順序   類似列表推導式,在列表推導式的基礎上添加了一個去除重複項

list1 = [1, 5, 35, 3, 5, 1]
set1 = {x - 1 for x in list1 if x > 5}
print(set1)

3、字典推導式

#字典推導式
#key與value進行交換
dict1 = {'a' : 'A', 'b' : 'B', 'c' : 'C', 'd' : 'C'}
newdict = {value : key for key, value in dict1.items()}
print(newdict)

 

二、生成器  generator

通過列表生成式(列表推導式),我們可以直接創建一個列表,但是受到內存限制,列表容量肯定是有限的。

而且,創建一個包含100萬個元素的列表,不僅佔用很大的存儲空間。

如果我們僅僅需要訪問前面幾個元素,那後面絕大多數元素佔用的空間都白白浪費了。

所以,如果列表元素可以按照某種算法推算出來,那我們是否可以在循環的過程中不斷推算出後續的元素呢?

這樣就不必創建完成的list,從而節省大量的空間。

在Python中,這種一邊循環一邊計算的機制,稱爲生成器:generator

 

得到生成器的方式:

方式一、通過列表推導式得到生成器

#得到列表[0, 3, 6, 9, 12, ..., 30]
newlist = [x * 3 for x in range(11)]
print(type(newlist))  #list

#得到生成器  將列表推導式外部[]  改爲 ()
g = (x * 3 for x in range(11))
print(type(g))  #generator
print(g)    #<generator object <genexpr> at 0x0000000001D6FA20>
#方式1:通過調用 __next__()
print(g.__next__())  #0
print(g.__next__())  #3  只有調用時,才產生

#方式2: next(生成器對象)  built-in系統內置函數
#每調用一次next(),則會產生一個元素
print(next(g))  #6
print(next(g))  #9
# StopIteration  生成器本來可以生成10個,現在得到了10個,如果繼續調用next(生成器) 會拋出異常

while True:
    try:
        e = next(g)
        print(e)
    except:
        print("沒有更多的元素")
        break

方式二、藉助函數完成  yield

函數中出現 yield,說明函數已經不是函數,而是生成器

步驟:

1、定義一個函數,函數中使用yield關鍵字

2、調用函數,接收調用的結果

3、得到的結果就是生成器

4、藉助於next(生成器) 或 __next__() 得到元素

def func1():
    n = 0
    while True:
        n += 1
        yield n  # return n + 暫停

g = func1()
print(g)  #generator
print(next(g))  # 1
print(next(g))  # 2

#裴波那切數列  0、1、1、2、3、5、8、13、21、34、55、89、144...
def fib(length):
    a, b = 0, 1
    n = 0
    while n < length:
        yield b  #return b + 暫停
        a, b = b, a + b  #再次調用,在yield 下方執行代碼
        n += 1
    return '沒有更多元素!'  #--->就是在得到StopIteration後提示信息

g = fib(8)
print(g.__next__())
print(g.__next__())
print(g.__next__())
print(g.__next__())

 

生成器的方法:

    __next__():  獲取下一個元素

    send(value): 向每次生成器調用中傳值  注意:第一次需要調用send(None)

 

生成器send(value) 方法:

def gen():
    i = 0
    while i < 5:
        temp = yield i #return i + pause
        print('temp', temp)
        i += 1
    return '沒有更多的數據'

g = gen()
n1 = g.send(None)
n1 = g.send("test")
print(n1)
n2 = g.send("aaa")
print(n2)

 

三、進程、線程、協程之間的關係

進程  包含多個  線程  包含多個  協程

例如:迅雷下載,同時10個線程

#一個進程可以開啓多個協程
def task1(n):
    for i in range(n):
        print("正在搬第{}塊磚".format(i))
        yield None

def task2(n):
    for i in range(n):
        print("正在聽第{}首歌".format(i))
        yield None

#未添加生成器,先搬磚,後聽歌,無法交替進行    添加生成器可以交替完成
g1 = task1(10)
g2 = task2(6)

while True:
    try:
        g1.__next__()
        g2.__next__()
    except:
        pass

 

四、總結生成器 generator

定義生成器的方式:

1、通過列表推導式構建

g = (x + 1 for x in range(10))

2、函數和yield

def func():

    ...

    yield

g = func()

 

產生元素:

1、next(generator)  --->每次調用都會產生一個新的元素,如果元素產生完畢,再次調用的話就會產生異常

2、生成器內置方法:

g.__next__()

g.send(value)

 

應用:協程

 

五、可迭代的 和 迭代器

可迭代的:

可迭代的對象: 1、生成器  2、元組、列表、集合、字典、字符串

如何判斷一個對象是否是可迭代的?

from collections import Iterable

isinstance(list1, Iterable)

迭代器:

迭代是訪問集合元素的一種方式,迭代器是一個可以記住遍歷的位置的對象。

特點:

1、迭代器對象從集合的第一個元素開始訪問,直到所有的元素被訪問完結束。

2、迭代器只能往前不會後退。

3、可以被next()函數調用並不斷返回下一個值的對象稱爲迭代器:Iterator

 

可迭代的 是否是 迭代器?

生成器是可迭代的,是迭代器

list是可迭代的,但不是迭代器

list ---> iter(list) ---> 迭代器 next()

from collections import Iterable

list1 = [1, 3, 5]
f = isinstance(list1, Iterable) 
print(f)

f = isinstance('abc', Iterable)
print(f)

f = isinstance(100, Iterable)
print(f)

g = (x for x in range(10))
f = isinstance(g, Iterable)
print(f)

#list  ---> 迭代器  通過iter()  函數可迭代的變成一個迭代器
list1 = [1, 3, 45, 9, 6]
i_list1 = iter(list1)
print(next(i_list1))
print(next(i_list1))

 

六、生成器和迭代器的關係

迭代器:可以調用next(generator)

迭代器:包含生成器

迭代器分爲兩大類:1、生成器是迭代器的一種

                                 2、藉助iter()  函數的轉換,轉換成迭代器

                                       例如:iter(list)    iter(tuple)

 

七、總結

列表推導式:

[表達式 for 變量 in 列表]

[x+2 for x in list1] ---> 新的列表

 

1、[表達式 for 變量 in 列表 if 條件]

    [x+2 for x in list1 if x % 2 == 0]

 

2、[結果A if 條件 else 結果B for x in list1]

    [x+2 if x % 2 == 0 else x + 1 for x in list1]

 

集合推導式: {表達式 for i in 列表}  --->類似列表推導式,但是沒有重複元素

字典推導式: {key, value for k, v in 字典.items()}

 

生成器:generator

1、使用類似的列表推導式 g = (表達式 for 變量 in 列表)

此時的g就是生成器

2、函數+yield

def func():

    ...

    yield

    ...

g = func()

 

得到裏面的元素:

系統函數: next(g)

生成器內置函數: __next__(),  [send(None), send(value)]

 

可迭代的與迭代器:

可迭代:1、生成器  2、字符串、列表、集合、元組

Iterable

isinstance(x, Iterable) --->true, false

 

迭代器:調用next(g)

生成器就是一個迭代器 --->next(g) --->下一個元素

next(list) ---> iter(list) ---> next(iter(list)) --->下一個元素

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章