Python迭代器與生成器
列表生成式
列表生成式也叫做列表推導式,它本身還是列表,只不過它是根據我們定義的規則來生成一個真實的列表。
list2 = [x
for
x
inrange
(
10
)]
print
(list2)
下面是一個複雜的列子:
list1 = [x * y
for
x
inrange
(
1
,
5
)
if
x >
2for
y
inrange
(
1
,
4
)
if
y <
3
]
# 上面的列表生成式等同於下面的程式碼
list4 = []
for
x
inrange
(
1
,
5
):
if
x >
2
:
for
y
inrange
(
1
,
4
):
if
y <
3
:
list4.append(x * y)
生成器
如果要建立一個100萬個元素的列表,你使用上面的方式無疑非常佔用記憶體,這時候就用到了生成器,它其實是儲存一個你定義的規則,在需要用到元素的時候按照規則去生成一個,而不是儲存好一大堆元素,這樣就減少記憶體佔用。不過生成器的元素只能順序依次獲取不能像真正列表那樣可以按位置獲取而且不能回退。
建立一個生成器,生成器儲存的是一個演算法,而不是具體的內容。可以看到和列表生成式的區別是就是把[]換成(),
generator = (x for x in range(10))
。其實生成器就是一個迭代器,只不過它是一種特殊的迭代器:
print
(
"generator是否是迭代器:"
,
isinstance
(generator, Iterator))
# 結果為 True
print
(
"generator是否是可迭代物件:"
,
isinstance
(generator, Iterable))
# 結果為 True
如果要想獲取生成器元素就只能透過next來獲取下一個元素,必須順序獲取,當沒有元素的時候丟擲 StopIteration 異常。
print(generator.__next__()) # 也可以這樣來使用 next(generator)
。用生成器實現斐波那契數列:
deffib
(
length
):
"""
生成器定義一個斐波那契數列,生成器本身就是yield + next實現。外部呼叫next來觸發一次計算
函式遇到yield返回,然後下一次next則繼續從上一次yield的地方向下執行,直到遇到某個結束條件
:param length:
:return:
"""
n, a, b =
0
,
0
,
1
while
n < length:
yield
b
"""
a, b = b, a + b 等於 t = (b, a + b) a=t[0] b=t[1] 當計算b = a + b的時候,
這裡的a並不是之前 a = b 之後a值,而是之前的a值,所以它是先做 = 右邊的計算,然後賦值給左邊的
"""
a, b = b, a + b
n = n +
1
return'done'
for
i
in
fib(
10
):
print
(i)
迭代器
可以用next()函式呼叫來獲取下一個元素的物件叫做迭代器。生成器就可以,但是普通集合類比如list、dict、str就不可以。集合類的物件比如list、dict、set、str;還有生成器都是可迭代物件,也就是可以遍歷的。但是它們並不一定都是迭代器。list、dict、str等資料型別不是Iterator。
list1 = [
1
,
2
,
3
,
4
,
5
,
6
]
print
(
"list1是否是迭代器:"
,
isinstance
(list1, Iterator))
# 結果為 False
print
(
"list1是否是可迭代物件:"
,
isinstance
(list1, Iterable))
# 結果為 True
print
(
"list1的長度:"
,
len
(list1))
# 結果為具體長度
ifhasattr
(list1,
"__next__"
):
print
(
"list1是迭代器"
)
把list1變成迭代器:
interObj =
iter
(list1)
print
(
"list1是否是迭代器:"
,
isinstance
(interObj, Iterator))
# 結果為 True
print
(
"list1是否是可迭代物件:"
,
isinstance
(interObj, Iterable))
# 結果為 False
# print("interObj的長度:", len(interObj)) # 無法獲取長度
ifhasattr
(interObj,
"__next__"
):
print
(
"interObj是迭代器"
)
-
可遍歷的物件不一定是迭代器,但是肯定是可迭代物件。
-
迭代器同時一定也是可迭代物件。生成器是一種特殊的迭代器,所以也是可迭代物件。
-
可迭代物件和迭代器最大的區別就是前者可以透過len()獲取長度而後者不能
-
且迭代器一定可以透過next()函式(說明該物件包含__next__內建方法)獲取下一個元素,而可迭代物件不一定。
連結:https://www.cnblogs.com/rexcheny/p/12305235.html
(版權歸原作者所有,侵刪)