日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Pyhton迭代器

發布時間:2023/12/15 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Pyhton迭代器 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

本文介紹python的一些高級特性,分別介紹列表生成式、生成器和迭代器。
三者之間有一些相互聯系的地方。
1、列表生成式(保存的是List)
列表生成式即List Comprehensions,是Python內置的非常簡單卻強大的可以用來創建list的生成式。
具體操作可看下面代碼:

>>> list(range(1, 11)) [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]>>> [x * x for x in range(1, 11)] [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]>>> [x * x for x in range(1, 11) if x % 2 == 0] [4, 16, 36, 64, 100]>>> [m + n for m in 'ABC' for n in 'XYZ'] ['AX', 'AY', 'AZ', 'BX', 'BY', 'BZ', 'CX', 'CY', 'CZ']#用兩個變量來生成list >>> d = {'x': 'A', 'y': 'B', 'z': 'C' } >>> [k + '=' + v for k, v in d.items()] ['y=B', 'x=A', 'z=C']>>> L = ['Hello', 'World', 'IBM', 'Apple'] >>> [s.lower() for s in L] ['hello', 'world', 'ibm', 'apple']

2、生成器(保存的是算法)
通過列表生成式,我們可以直接創建一個列表。但是,受到內存限制,列表容量肯定是有限的。而且,創建一個包含100萬個元素的列表,不僅占用很大的存儲空間,如果我們僅僅需要訪問前面幾個元素,那后面絕大多數元素占用的空間都白白浪費了。

所以,如果列表元素可以按照某種算法推算出來,那我們是否可以在循環的過程中不斷推算出后續的元素呢?這樣就不必創建完整的list,從而節省大量的空間。在Python中,這種一邊循環一邊計算的機制,稱為生成器:generator。

要創建一個generator,有很多種方法。第一種方法很簡單,只要把一個列表生成式的[]改成(),就創建了一個generator:

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

我們可以直接打印出list的每一個元素,但我們怎么打印出generator的每一個元素呢?如果要一個一個打印出來,可以通過next()函數獲得generator的下一個返回值。

>>> next(g) 0 >>> next(g) 1 >>> next(g) 4 >>> next(g) 9 >>> next(g) 16 >>> next(g) Traceback (most recent call last):File "<stdin>", line 1, in <module> StopIteration

我們講過,generator保存的是算法,每次調用next(g),就計算出g的下一個元素的值,直到計算到最后一個元素,沒有更多的元素時,拋出StopIteration的錯誤。
當然,上面這種不斷調用next(g)實在是太變態了,正確的方法是使用for循環,因為generator也是可迭代對象:

>>> g = (x * x for x in range(5)) >>> for n in g: ... print(n) ... 0 1 4 9 16

斐波拉契數列用列表生成式寫不出來,但是,用函數把它打印出來卻很容易:

def fib(max):n, a, b = 0, 0, 1while n < max:print(b)a, b = b, a + bn = n + 1return 'done' ''' 注意,賦值語句: a, b = b, a + b 相當于: t = (b, a + b) # t是一個tuple a = t[0] b = t[1] '''

上面的函數可以輸出斐波那契數列的前N個數:

>>> fib(6) 1 1 2 3 5 8 'done'

仔細觀察,可以看出,fib函數實際上是定義了斐波拉契數列的推算規則,可以從第一個元素開始,推算出后續任意的元素,這種邏輯其實非常類似generator。

也就是說,上面的函數和generator僅一步之遙。要把fib函數變成generator,只需要把print(b)改為yield b就可以了:

def fib(max):n, a, b = 0, 0, 1while n < max:yield ba, b = b, a + bn = n + 1return 'done'

這就是定義generator的第二種方法。如果一個函數定義中包含yield關鍵字,那么這個函數就不再是一個普通函數,而是一個generator:

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

這里,最難理解的就是generator和函數的執行流程不一樣。函數是順序執行,遇到return語句或者最后一行函數語句就返回。而變成generator的函數,在每次調用next()的時候執行,遇到yield語句返回,再次執行時從上次返回的yield語句處繼續執行。
用for循環調用generator時,發現拿不到generator的return語句的返回值。如果想要拿到返回值,必須捕獲StopIteration錯誤,返回值包含在StopIteration的value中:

>>> g = fib(6) >>> while True: ... try: ... x = next(g) ... print('g:', x) ... except StopIteration as e: ... print('Generator return value:', e.value) ... break ... g: 1 g: 1 g: 2 g: 3 g: 5 g: 8 Generator return value: done

3、迭代器
我們已經知道,可以直接作用于for循環的數據類型有以下幾種:
一類是集合數據類型,如list、tuple、dict、set、str等;
一類是generator,包括生成器(…)和帶yield的generator function。
這些可以直接作用于for循環的對象統稱為可迭代對象:Iterable。
可以使用isinstance()判斷一個對象是否是Iterable對象:

>>> from collections import Iterable >>> isinstance([], Iterable) True >>> isinstance((), Iterable) True >>> isinstance({}, Iterable) True >>> isinstance('abc', Iterable) True >>> isinstance((x for x in range(10)), Iterable) True >>> isinstance(100, Iterable) False

而生成器不但可以作用于for循環,還可以被next()函數不斷調用并返回下一個值,直到最后拋出StopIteration錯誤表示無法繼續返回下一個值了。
可以被next()函數調用并不斷返回下一個值的對象稱為迭代器:Iterator。
可以使用isinstance()判斷一個對象是否是Iterator對象:

>>> from collections import Iterator >>> isinstance((x for x in range(10)), Iterator) True >>> isinstance([], Iterator) False >>> isinstance({}, Iterator) False >>> isinstance('abc', Iterator) False

生成器都是Iterator對象,但list、dict、str雖然是Iterable,卻不是Iterator。
把list、dict、str等Iterable變成Iterator可以使用iter()函數:

>>> isinstance(iter([]), Iterator) True >>> isinstance(iter('abc'), Iterator) True

你可能會問,為什么list、dict、str等數據類型不是Iterator?
這是因為Python的Iterator對象表示的是一個數據流,Iterator對象可以被next()函數調用并不斷返回下一個數據,直到沒有數據時拋出StopIteration錯誤??梢园堰@個數據流看做是一個有序序列,但我們卻不能提前知道序列的長度,只能不斷通過next()函數實現按需計算下一個數據,所以Iterator的計算是惰性的,只有在需要返回下一個數據時它才會計算。
Iterator甚至可以表示一個無限大的數據流,例如全體自然數。而使用list是永遠不可能存儲全體自然數的。

小結
凡是可作用于for循環的對象都是Iterable類型;
凡是可作用于next()函數的對象都是Iterator類型,它們表示一個惰性計算的序列;
集合數據類型如list、dict、str等是Iterable但不是Iterator,不過可以通過iter()函數獲得一個Iterator對象。
Python的for循環本質上就是通過不斷調用next()函數實現的,例如:
for x in [1, 2, 3, 4, 5]:
pass
實際上完全等價于:

# 首先獲得Iterator對象: it = iter([1, 2, 3, 4, 5]) # 循環: while True:try:# 獲得下一個值:x = next(it)except StopIteration:# 遇到StopIteration就退出循環break

詳細請參考:
https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/00143178254193589df9c612d2449618ea460e7a672a366000

總結

以上是生活随笔為你收集整理的Pyhton迭代器的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。