Python基礎 - 06推導式及生成器
阿新 • • 發佈:2021-10-14
Python基礎 - 06推導式及生成器
一、列表推導式
格式: [表示式for變數in舊列表] [表示式for變數 in舊列表if條件]
names = ['tom', 'lily', 'abc', 'Hello', 'Jack', 'lucy'] result1 = [name for name in names if len(name) > 3] print(result1) # ['lily', 'Hello', 'Jack', 'lucy'] result2 = [name.capitalize() for name in names if len(name) <= 3] print(result2) # ['Tom', 'Abc'] # 將1-100之間被3整除的數字組成一個列表 result3 = [num for num in range(1, 101) if num % 3 == 0] print(result3) result4 = [num for num in range(1, 101) if num % 3 == 0 and num % 5 == 0] print(result4)
# 0-5 偶數 0-10 奇數 (0,1) (0,3) ... (0,9) (2,1) (2,3) ... result5 = [(x, y) for x in range(5) if x % 2 == 0 for y in range(10) if y % 2 != 0] print(result5)
employee1 = {'name': 'zhangsan', 'salary': 4300} employee2 = {'name': 'lisi', 'salary': 5500} emp = [employee1, employee2] n = [employee['salary'] + 200 ifemployee['salary'] > 4500 else employee['salary'] + 500 for employee in emp] print(n) # [4800, 5700]
二、字典推導式、集合推導式
list1 = [1, 2, 3, 1, 5, 3, 2, 6, 8, 9, 8, 8, 9]
set1 = {x - 1 for x in list1 if x > 5} # 類似列表推導式,沒有重複元素
print(set1) # {8, 5, 7}
dict1 = {'k1': 'v1', 'k2': 'v2'}
newdict = {value: key for key, value in dict1.items() }
print(newdict) # {'v1': 'k1', 'v2': 'k2'}
三、生成器
使用列表推導式生成列表,但受到記憶體限制,容量有限。建立一個100萬元素的列表,僅僅需要訪問前面幾個元素,造成空間浪費。
邊迴圈邊計算的機制,稱為生成器,generator
next(generator):每次呼叫都會產生一個新的元素,如果元素都產生完畢,再次呼叫會產生異常。
生成器方法:g.__next__() g.send(value)
3.1定義生成器
list2 = [x * 3 for x in range(10)]
print(type(list2)) # <class 'list'>
g = (x * 3 for x in range(5))
print(type(g)) # <class 'generator'>
print(g) # <generator object <genexpr> at 0x000000DC2790DF90>
print(g.__next__()) # 0
print(g.__next__()) # 3
print(g.__next__()) # 6
print(next(g)) # 9
print(next(g)) # 12
#print(next(g)) # StopIteration
3.2使用try...except結構讀取生成器元素;讀取讀取的方式 next(g)或g.__next__()
while True:
try:
e = next(g)
print(e)
except:
print('沒有元素啦')
break
print('測試結束')
'''
0
3
6
9
12
沒有元素啦
測試結束
'''
3.3定義生成器方式:函式
# 定義生成器方式二: 函式
# 只要函式中出現yield關鍵字,則函式不再是函式,變成生成器了。
def func6():
n = 0
while True:
n += 1
# print(n)
yield n # 效果等同於 return n + 暫停
g = func6()
print(g) # <generator object func6 at 0x0000008356E8DF20>
print(next(g)) # 1
print(next(g)) # 2
使用生成器實現斐波那契數列:
def fib(length): a, b = 0, 1 n = 0 while n < length: yield b a, b = b, a + b n += 1 g = fib(8) print(next(g)) # 1 print(next(g)) # 1 print(next(g)) # 2 print(next(g)) # 3 print(next(g)) # 5 print(next(g)) # 8 print(next(g)) # 13 print(next(g)) # 21
def fib(length): a, b = 0, 1 n = 0 while n < length: print(b) a, b = b, a + b n += 1 fib(8) # 也能實現輸出 1 1 2 3 5 8 13 21
3.4生成器帶return語句
def fib(length): a, b = 0, 1 n = 0 while n < length: yield b a, b = b, a + b n += 1 return 'abc' g = fib(8) print(next(g)) # 1 print(next(g)) # 1 print(next(g)) # 2 print(next(g)) # 3 print(next(g)) # 5 print(next(g)) # 8 print(next(g)) # 13 print(next(g)) # 21 print(next(g)) # StopIteration: abc ;沒有 return時,報錯StopIteration
3.5send方法:向生成器中傳值
def gen():
i = 0
while i < 5:
temp = yield i
print('temp: ', temp)
i += 1
return '沒有資料了'
g = gen()
print(g.__next__()) # 0
print(g.__next__()) # temp: None \n 1
print(g.__next__()) # temp: None \n 2
n1 = g.send('呵呵')
print('n1: ', n1) # temp: 呵呵 \n n1: 3
n2 = g.send('哈哈')
print('n2: ', n2) # temp: 哈哈 \n n2: 4
n3 = g.send(None) # temp: None \n StopIteration: 沒有資料了, 取值時沒有了報錯,賦值成功
print('n3: ', n3) # 這個沒有執行
直接往生成器非None傳值報錯
g = gen() # print(g.__next__()) # print(g.__next__()) # print(g.__next__()) n1 = g.send('呵呵') # 報錯: # TypeError: can't send non-None value to a just-started generator
g = gen() print(g.send(None)) # 改成 n = g.send(None) 也可以 n1 = g.send('呵呵') print('n1: ', n1) ''' 0 temp: 呵呵 n1: 1 '''
def gen1():
i = 0
while i < 5:
temp = yield i
print('temp: ', temp)
for i in range(temp):
print('------->', i)
print('**************')
i += 1
return '沒有資料了'
g1 = gen1()
print(g1.send(None))
n1 = g1.send(3)
print('n1:',n1)
'''
0
temp: 3
-------> 0
-------> 1
-------> 2
**************
n1: 3
'''
n2 = g1.send(4)
print('n2:', n2)
'''
temp: 4
-------> 0
-------> 1
-------> 2
-------> 3
**************
n2: 4
'''
def task1(n):
for i in range(n):
print('正在搬第{}塊磚'.format(i+1))
yield None
def task2(n):
for i in range(n):
print('正在聽第{}首歌'.format(i+1))
yield None
g1 = task1(3)
g2 = task2(2)
while True:
g1.__next__()
g2.__next__()
'''
正在搬第1塊磚
正在聽第1首歌
正在搬第2塊磚
正在聽第2首歌
正在搬第3塊磚
Traceback (most recent call last):
File "E:\PythonLearn\pythonBase\02door2\08-generator-03.py", line 23, in <module>
g2.__next__()
StopIteration
'''
處理異常:
while True: try: g1.__next__() g2.__next__() except: pass
3.6可迭代與迭代器
# 可迭代的物件 1. 生成器 2. 元祖 列表 集合 字典 字串
# 如何判斷一個物件是否可迭代
from collections import Iterable
list1 = [1,2,46,5,3]
result = isinstance(list1, Iterable)
print(result) # True
result = isinstance('abc', Iterable)
print(result) # True
result = isinstance(100, Iterable)
print(result) # False
迭代是訪問集合元素的一種方式。迭代器是一個可以記住遍歷位置的物件。
迭代器物件從集合的第一個元素開始訪問,直到所有元素都被訪問完結束。迭代器只能往前不會後退。
# 可以被next()函式呼叫並返回下一個值的物件稱為迭代器:Iterable。
# 可迭代的 不一定就是迭代器。
# 生成器是可迭代的,是迭代器。 list是可迭代的,但不是迭代器。
list1 = iter(list1)
print(next(list1)) # 1
print(next(list1)) # 2