前幾天遇到了這個yield,不知道是干嘛的,這里學習整理下,主要參考了:
如何理解Python關鍵字yield
Python高級特性
上面介紹的都很好,這里就根據自己的理解,簡單整理下。
1. 什么是迭代
常見的list、tuple等集合,我們會通過遍歷,比如for循環來獲取每一個元素,這就是迭代。這些可以遍歷的對象,也叫做可迭代對象
小例子
a = [1,2,3]
print(a)
for i in a:
print(i)
b = 'abcd'
print(b)
for i in b:
print(i)
c = {'name':'lufei','age':20}
print(c)
for k in c:
print(k)
for v in c.values():
print(v)
for k,v in c.items():
print(k,v)
#out
[1, 2, 3]
1
2
3
abcd
a
b
c
d
{'name': 'lufei', 'age': 20}
name
age
lufei
20
name lufei
age 20
我們怎樣判斷一個對象是否可以去迭代呢?可以使用collections模塊的Iterable
print(type(a),isinstance(a,Iterable))
print(type(b),isinstance(b,Iterable))
print(type(c),isinstance(c,Iterable))
print(type(123),isinstance(123,Iterable))
#out
<class 'list'> True
<class 'str'> True
<class 'dict'> True
<class 'int'> False
2. 列表生成式(List Comprehensions)
一個非常簡單的方式來生成list,像這樣:
range(10)
Out[56]: range(0, 10)
list(range(10))
Out[57]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
list(x for x in range(10))
Out[58]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
list(x*x for x in range(10))
Out[59]: [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
[x*x for x in range(3)]
Out[60]: [0, 1, 4]
#上面的for后面還可以加上if判斷
[x for x in range(10) if x>5]
Out[61]: [6, 7, 8, 9]
#for循環也可以嵌套
[x+y for x in 'abc' for y in 'xyz']
Out[62]: ['ax', 'ay', 'az', 'bx', 'by', 'bz', 'cx', 'cy', 'cz']
3.迭代器
前面,我們說了for循環和可迭代對象,像這種可以使用for循環不斷取出先一個元素的對象,就叫做迭代器(Iterator)。迭代器不單單可以使用for循環來遍歷,
還可以使用next()函數不斷獲取下一個元素,當沒有下一個元素時,會拋出StopIteration異常。
我們可以使用collections模塊的Iterator來判斷一個對象是否為迭代器
from collections import Iterator
isinstance([1,2,3],Iterator)
Out[2]: False
isinstance('abc',Iterator)
Out[3]: False
isinstance({'name':'lufei','age':20},Iterator)
Out[4]: False
創建一個迭代器有3中方式:
- 為對象創建 iter()和next()方法
- 內置的iter()可以將可迭代對象轉換為迭代器
- 生成器
a = [1,2,3]
type(iter(a))
Out[6]: list_iterator
isinstance(iter(a),Iterator)
Out[7]: True
4. 生成器
上面,我們使用list()或者[],很簡單方便的生成了一個列表,只要我們將[]替換為(),就創建一個一個generator。生成器可以一邊循環,一邊計算生成下一個元素,而不是像list一樣,一下生成所有的數據。
(x+y for x in 'abc' for y in 'xyz')
Out[63]: <generator object <genexpr> at 0x0000021AE0FC9D58>
a = (x+y for x in 'abc' for y in 'xyz')
a
Out[66]: <generator object <genexpr> at 0x0000021AE0FC9518>
isinstance(a,Iterator)
Out[67]: True
通常,我們使用yield語句可以返回一個生成器,很多例子,這里都是舉一個斐波那契數列
yield類似return,只不過他返回的是生成器,調用了next()之后,
def fab(n):
a,b,i = 0,1,0
while i<n:
print(b)
a,b = b,a+b
i+=1
fab(5)
#out
1
1
2
3
5
#使用yield改造
def fab(n):
a,b,i = 0,1,0
while i<n:
yield b
a,b = b,a+b
i+=1
for i in fab(5):
print(i)
我們調用fab的時候,執行到yield,會返回一個生成器,當調用next()后,程序會回到yield停止的地方繼續往下執行
這樣,就是每次只生成當前元素,而不是一下子生成所有的元素;
當然,for循環替我們調用了next(),并處理了StopIteration異常。
好了,梳理好上面這些概念,到yield這里,其實還好,平時在理解下,多用用,好,就到這。