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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

python throw_Python 生成器与它的 send,throw,close 方法(转帖以及记录)

發布時間:2025/3/13 python 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python throw_Python 生成器与它的 send,throw,close 方法(转帖以及记录) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Python 生成器與它的 send,throw,close 方法

在生成器中,無論生成器是什么狀態,都可以直接使用throw與close。

生成器這一塊,對于next,send網上的介紹比較多,但對于throw以及close很多書上寫的比較少,可能用的比較少,好在網上有很多介紹。

以下是流暢的Python對throw和close的介紹:

generator.throw(exc_type[, exc_value[, traceback]])

致使生成器在暫停的yield表達式處拋出指定的異常。如果生成器處理了拋出的異常,代碼會向前執行到下一個yield表達式,而產出的值會調用generator.throw方法得到的返回值。如果生成器沒有處理拋出的異常,異常會向上冒泡,傳到調用方的上下文中。

generator.close()

致使生成器在暫停的yield表達式處拋出GeneratorExit異常。如果生成器沒有處理這個異常,或者拋出了StopIteration異常(通常是指運行到結尾),調用方不會報錯。如果收到GeneratorExit異常,生成器一定不能產出值,否則解釋器會拋出RuntimeError異常。生成器拋出的其他異常會向上冒泡,傳給調用方。

next就是send(None)

生成器第一次需要預激,到達第一個yield處,預激可以用next或send(None),預激將產出第一個值,并到達第一個yield處

到達yield處可以send(object)了。

In [319]: def demo():

...: for i in range(5):

...: res = yield i

...: print(res)

...:

In [320]: d = demo()

In [321]: type(d)

Out[321]: generator

In [322]: next(d)

Out[322]: 0

In [323]: d.send('ok')

ok

Out[323]: 1

In [324]: d.send(None)

None

Out[324]: 2

In [325]: next(d)

None

Out[325]: 3

In [326]: next(d)

None

Out[326]: 4

In [327]: next(d)

None

---------------------------------------------------------------------------

StopIteration Traceback (most recent call last)

in

----> 1 next(d)

StopIteration:

In [328]: next(d)

---------------------------------------------------------------------------

StopIteration Traceback (most recent call last)

in

----> 1 next(d)

StopIteration:

簡單的測試了next與send,接著測試throw.

按照前面書中的說明,throw以后如果抓取到錯誤,執行except內的語句,然后尋找下一個yield,所以如果在最后一個yield處throw,就算抓取在生成器中抓取到錯誤也會上浮錯誤信息

StopIteration。當throw進去一個錯誤,生成器內部沒有處理,當外部調用生成器的時候捕獲了上浮的錯誤,此時生成器已經關閉,如果再次使用next與send會包stopIteration。

(這里我重點筆記一下throw(StopIteration),因為當throw這個的時候,報的錯誤是RuntimeError)

In [1]: def xx():

...: yield 1

...:

In [2]: x = xx()

In [3]: x.throw(NameError)

---------------------------------------------------------------------------

NameError Traceback (most recent call last)

in

----> 1 x.throw(NameError)

in xx()

----> 1 def xx():

2 yield 1

3

NameError:

In [4]: x = xx()

In [5]: next(x)

Out[5]: 1

In [6]: x.throw(NameError)

---------------------------------------------------------------------------

NameError Traceback (most recent call last)

in

----> 1 x.throw(NameError)

in xx()

1 def xx():

----> 2 yield 1

3

NameError:

In [7]:

上面這個是普通的沒有去獲取任何異常的情況下,可以發現,生成器沒有預激的情況下,也可以throw錯誤,只不過上浮的錯誤顯示,報錯的方位不一樣。

沒有預激的生成器在def處就發現了錯誤,預激的生成器在第一個yield處發生了錯誤。

我測試了很多不同的錯誤,一般不管在預激還是沒有預激的情況下,扔什么錯誤,在沒有捕獲的情況下,就上浮錯誤,但StopIterations是一個例外。

In [33]: def xx():

...: yield 1

...: yield 2

...:

In [34]: x = xx()

In [35]: next(x)

Out[35]: 1

In [37]: try:

...: x.throw(ValueError,'ValueError_my')

...: except ValueError as e:

...: print(e)

...:

ValueError_my

In [38]: inspect.getgeneratorstate(x)

Out[38]: 'GEN_CLOSED'

In [39]: next(x)

---------------------------------------------------------------------------

StopIteration Traceback (most recent call last)

in

----> 1 next(x)

StopIteration:

上面是一個沒有捕獲錯誤,外部捕獲了錯誤,但生成器已經關閉了。

In [40]: def xx():

...: try:

...: yield 1

...: yield 2

...: except TypeError:

...: print('info type error')

...:

...:

In [41]: x = xx()

In [42]: x.throw(TypeError)

---------------------------------------------------------------------------

TypeError Traceback (most recent call last)

in

----> 1 x.throw(TypeError)

in xx()

----> 1 def xx():

2 try:

3 yield 1

4 yield 2

5 except TypeError:

TypeError:

In [43]: x = xx()

In [44]: next(x)

Out[44]: 1

In [45]: x.throw(TypeError)

info type error

---------------------------------------------------------------------------

StopIteration Traceback (most recent call last)

in

----> 1 x.throw(TypeError)

StopIteration:

In [46]: def xx():

...: try:

...: yield 1

...: yield 2

...: except TypeError:

...: print('info type error')

...: yield 3

...:

...:

...:

In [47]: x = xx()

In [48]: next(x)

Out[48]: 1

In [49]: x.throw(TypeError)

info type error

Out[49]: 3

In [50]: next(x)

---------------------------------------------------------------------------

StopIteration Traceback (most recent call last)

in

----> 1 next(x)

StopIteration:

In [51]:

上面的例子測試了沒有預激的情況下,throw錯誤,生成器內部完全不能捕獲任何沒有預激情況下的錯誤,而且該生成器也將關閉。

在預激的情況下,可以捕獲設置的錯誤,并且尋找下一個yield,如果沒有下一個yield,上浮StopIteration

In [54]: def xx():

...: try:

...: yield 1

...: yield 2

...: except StopIteration:

...: print('info stop')

...: yield 3

...:

...:

...:

In [55]: x = xx()

In [56]: x.throw(StopIteration)

---------------------------------------------------------------------------

StopIteration Traceback (most recent call last)

in xx()

----> 1 def xx():

2 try:

3 yield 1

StopIteration:

The above exception was the direct cause of the following exception:

RuntimeError Traceback (most recent call last)

in

----> 1 x.throw(StopIteration)

RuntimeError: generator raised StopIteration

In [57]: x = xx()

In [58]: next(x)

Out[58]: 1

In [59]: x.throw(StopIteration)

info stop

Out[59]: 3

In [60]: x.throw(StopIteration)

---------------------------------------------------------------------------

StopIteration Traceback (most recent call last)

in xx()

6 print('info stop')

----> 7 yield 3

8

StopIteration:

The above exception was the direct cause of the following exception:

RuntimeError Traceback (most recent call last)

in

----> 1 x.throw(StopIteration)

RuntimeError: generator raised StopIteration

In [61]:

從上面的列子可以看出只要沒有捕獲StopItoration,就上浮RuntimeError,而且這個錯誤是就因為StopItoration引起的。

但如果在生成器內部預設了捕獲StopItoration,則還是跟不同的邏輯是一樣的。

我的理解為,應該為如果沒有捕獲StopItoration,直接用了什么方法調用生成了新的錯誤,上浮給調用者,避免與StopItoration錯誤重復。

最后是close,按照書中的說法跟我自己的理解,就是在yield處拋出Generation,可以通過except捕獲到錯誤,但捕獲了以后,后面不能再有yield產出值,要不然包RuntimeError。

就算不捕獲也沒關系,不會上浮任何的錯誤,只不過該協程已經關閉了。

In [61]: def xx():

...: try:

...: yield 1

...: yield 2

...: except GeneratorExit:

...: print('info stop')

...: yield 3

...:

...:

...:

...:

In [62]: x= xx()

In [63]: x.close()

In [64]: next(x)

---------------------------------------------------------------------------

StopIteration Traceback (most recent call last)

in

----> 1 next(x)

StopIteration:

In [65]: x= xx()

In [66]: next(x)

Out[66]: 1

In [67]: x.close()

info stop

---------------------------------------------------------------------------

RuntimeError Traceback (most recent call last)

in

----> 1 x.close()

RuntimeError: generator ignored GeneratorExit

In [68]: x= xx()

In [69]: next(x)

Out[69]: 1

In [70]: x.throw(GeneratorExit)

info stop

Out[70]: 3

最后,我自己總結一下thorw與close的筆記,兩個函數都可以不需要預激的情況下面執行。

但執行的時候,生成器內部不會捕獲到該異常。

預激了以后,throw所有的異常都能捕獲,捕獲到該異常后,向下執行尋找下一個yield,產出值,沒有yield就上浮StopItoration

close在預激了以后,能通過except捕獲到該GeneratorExit異常,但except向下的代碼不能出現yield產出值,要不然會拋出RuntimeError。

如果throw(StopItoration),如果沒有捕獲該錯誤,上浮的錯誤為RuntimeError。

一個生成器關閉了,還能繼續使用close函數,且不會報錯。

最后,一個生成器內部如果發生錯誤,沒有捕獲,這個生成器就馬上進行關閉。

總結

以上是生活随笔為你收集整理的python throw_Python 生成器与它的 send,throw,close 方法(转帖以及记录)的全部內容,希望文章能夠幫你解決所遇到的問題。

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