中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Python通過for循環理解迭代器和生成器實例詳解

發布時間:2020-10-03 21:44:32 來源:腳本之家 閱讀:146 作者:Waspvae 欄目:開發技術

本文實例講述了Python通過for循環理解迭代器和生成器。分享給大家供大家參考,具體如下:

迭代器

可迭代對象

通過 for…in… 循環依次拿到數據進行使用的過程稱為遍歷,也叫迭代。我們把可以通過 for…in… 語句迭代讀取數據的對象稱之為可迭代對象。

- 通過 isinstance()可以判斷一個對象是否可以迭代

# 判斷列表
print(isinstance([], Iterable)

打印結果為 True 即為可迭代對象。

- 自定義一個能容納數據的類,測試該類的可迭代性

import collections
class MyClassmate(object):
  def __init__(self):
    self.names = []
  def add(self, name):
    self.names.append(name)
# 創建 MyClassmate對象
my_classmate = MyClassmate()
my_classmate.add("小王")
my_classmate.add("小李")
my_classmate.add("小張")
# 判斷MyClassmate是否為可迭代對象
print("是否為可迭代對象:",isinstance(my_classmate, collections.Iterable))
# 迭代數據
for temp in my_classmate:
  print(temp)

運行結果:

是否為可迭代對象: False
Traceback (most recent call last):
    for temp in my_classmate:
TypeError: 'MyClassmate' object is not iterable

封裝一個可以存放多條數據的類型是不可迭代的

何為可迭代對象

  • 我們分析對可迭代對象進行迭代使用的過程,發現每迭代一次(即在 for…in… 中每循環一次)都會返回對象中的下一條數據,一直向后讀取數據直到迭代了所有數據后結束。那么,在這個過程中就應該有一個"人"去記錄每次訪問到了第幾條數據,以便每次迭代都可以返回下一條數據。我們把這個能幫助我們進行數據迭代的"人"稱為迭代器 (Iterator)。
  • 可迭代對象的本質就是提供一個這樣的中間"人"即迭代器幫助我們對其進行迭代遍歷使用。
  • 可迭代對象通過__iter__方法向我們提供一個迭代器,在迭代一個可迭代對象的時候,實際上就是先獲取該對象提供的一個迭代器,然后通過這個迭代器來依次獲取對象中的每一個數據.

1.可迭代對象的本質就是提供一個這樣的中間"人"即迭代器幫助我們對其進行迭代遍歷使用

2.可迭代對象是一個具備了__iter__方法的對象,通過__iter__方法獲取可迭代對象的迭代器

from collections import Iterable
class MyClassmate(object):
  def __init__(self):
    self.names = []
  def add(self, name):
    self.names.append(item)
  def __iter__(self):
    """空實現該方法"""
    return None
# 創建 MyClassmate對象
my_classmate = MyClassmate()
my_classmate.add("小王")
my_classmate.add("小李")
my_classmate.add("小張")
# 判斷MyClassmate是否為可迭代對象
print(isinstance(my_classmate, Iterable))

運行結果:

是否為可迭代對象: True

這回測試發現添加了__iter__方法的my_classmate對象已經是一個可迭代對象了。

iter() 函數與 next() 函數

list、tuple 等都是可迭代對象,我們可以通過 iter() 函數獲取這些可迭代對象的迭代器。然后我們可以對獲取到的迭代器不斷使用 next() 函數來獲取下一條數據。

li = [11, 22, 33, 44, 55]
# 通過iter() 取得可迭代對象的迭代器
iterator = iter(li)
# 通過next()函數取得iterator迭代器指向的下一個值
print(next(iterator))
print(next(iterator))
print(next(iterator))
print(next(iterator))
print(next(iterator))
print(next(iterator))

1.iter(iterable) 函數是把可迭代對象的迭代器取出來,內部是調用可迭代對象的__iter__方法,來取得迭代器的

2.next(iterator) 函數是通過迭代器取得下一個位置的值,內部是調用迭代器對象的__next__方法,來取得下一個位置的值

注意: 當我們已經迭代完最后一個數據之后,再次調用 next() 函數會拋出 StopIteration 的異常,來告訴我們所有數據都已迭代完成,不用再執行 next() 函數了。

迭代器

我們要想構造一個迭代器,就要實現它的__next__ 方法。但這還不夠,python 要求迭代器本身也是可迭代的,所以我們還要為迭代器實現__iter__ 方法,而 __iter__ 方法要返回一個迭代器,迭代器自身正是一個迭代器,所以迭代器的 __iter__ 方法返回自身即可。

一個實現了 __iter__ 方法和 __next__ 方法的對象,就是迭代器,迭代器同時也是一個可迭代對象.

import collections
class MyClassmate(object):
  def __init__(self):
    # 聲明一個列表
    self.names = []
    # 記錄迭代器迭代的位置, 默認是0 ,即從起始位置開始
    self.current = 0
  def add(self, name):
    self.names.append(name)
  def __iter__(self):
    """通過該方法取得迭代器對象"""
    return self
  def __next__(self):
    """取得下一個迭代的值"""
    if self.current < len(self.names):
      name = self.names[self.current]
      self.current += 1
      return name
    else:
      raise StopIteration
# 創建MyClassmate實例
my_classmate = MyClassmate()
my_classmate.add("小王")
my_classmate.add("小李")
my_classmate.add("小張")
# 測試MyList是不是可迭代對象
print(isinstance(my_classmate, collections.Iterable))
# 遍歷數據
for name in my_classmate:
  print(name)

for…in… 循環的本質

for item in Iterable 循環的本質就是先通過iter()函數獲取可迭代對象 Iterable 的迭代器,然后對獲取到的迭代器不斷調用 next() 方法來獲取下一個值并將其賦值給 item,當遇到 StopIteration 的異常后循環結束 (for…in..會自動處理 StopIteration 異常)。

生成器

生成器

生成器是一種特殊的迭代器,它比迭代器更優雅

創建生成器的方法

1.將列表生成式的 [] 改成 ()

# 參考列表生成式
L=[x*2 for x in range(6)]
print(L)
# 把[] 改為() :就是一個簡單的列表生成器
G=(x*2 for x in range(6))
# 輸出的是生成器對象
print(G)
print("通過next()函數取得下一個值")
print(next(G))
print(next(G))
print(next(G))
print(next(G))
print(next(G))
print(next(G))
# 創建一個簡單生成器,通過 for來遍歷
G=(x*2 for x in range(6))
print("通過for 迭代的結果:")
for num in G:
  print(num)

運行結果:

[0, 2, 4, 6, 8, 10]
<generator object <genexpr> at 0x7ff7f8bbd5c8>
通過next()函數取得下一個值
0
2
4
6
8
10
通過for 迭代的結果:
0
2
4
6
8
10

2.通過關鍵字 yield 實現生成器

def fib(n):
  current_index = 0
  num1, num2 = 0, 1
  while current_index < n:
    # print(num1) # 打印斐波那契數列
    """
     1. 假如函數中有yield,則不再是函數,而是生成器
     2. yield 會產生一個斷點
     3. 假如yield后面緊接著一個數據,就會把數據返回,
      作為next()函數或者for ...in...迭代出的下一個值
    """
    yield num1
    num1, num2 = num2, num1 + num2
    current_index += 1
if __name__ == '__main__':
  # 假如函數中有yield,則不再是函數,而是一個生成器
  gen = fib(5)
  #  生成器是一種特殊的迭代器
  for num in gen:
    print(num)
  # 也可以用 next() 函數取下一個值

在使用生成器實現的方式中,我們將原本在迭代器__next__方法中實現的基本邏輯放到一個函數中來實現,但是將打印輸出方式換成 yield,此時新定義的函數便不再是函數,而是一個生成器了。簡單來說:只要在函數中有 yield 關鍵字,就稱為生成器。

此時按照調用函數的方式( 案例中為 gen = fib(5) )使用生成器就不再是執行函數體了,而是會返回一個生成器對象( 案例中為 gen ),然后就可以按照使用迭代器的方式來使用生成器了。

使用 send() 喚醒

def gen():
  i = 0
  while i < 5:
    temp = yield i
    print(temp)
    i += 1
if __name__ == '__main__':
  # 取得生成器對象
  obj = gen()
  # 使用next()喚醒生成器
  print(next(obj))
  print(next(obj))
  # 使用send喚醒生成器 ,在喚醒的同時向斷點處傳入一個附加數據
  print(obj.send("haha"))
  # 使用next()喚醒生成器
  print(next(obj))
  # 使用send喚醒生成器 ,在喚醒的同時向斷點處傳入一個附加數據
  print(obj.send("python"))

運行結果:

0
None
1
haha
2
None
3
python

我們除了可以使用 next() 函數來喚醒生成器繼續執行外,還可以使用 send() 函數來喚醒執行。使用 send() 函數的一個好處是可以在喚醒的同時向斷點處傳入一個附加數據。

總結

1. 假如函數中有 yield,則不再是函數,而是生成器
2. yield 會產生一個斷點,暫停函數,保存狀態
3. 假如yield后面緊接著一個數據,就會把數據返回,作為 next() 函數或者 for …in… 迭代出的下一個值
4. 可以通過 next() 喚醒生成器,讓生成器從斷點處繼續執行

send與next喚醒生成器不同:

1. send 與next都可以喚醒生成器,但send(value)可以傳值給生成器的斷點處
2. 使用:

next(generator)
generator.send("你好")

3. generator.send(None)等價于next(generator)
4. 注意: 第一次喚醒生成器時,假如使用 send,則只能傳 None,因為剛開始執行生成器時,是沒有斷點的

- 解析

temp = yield num
generator.send("你好")

temp = yield num 為賦值語句,當看到等號時, 一定是等號左邊先運行完,再賦值給等號右邊

而程序運行到 yield num 時,會先返回一個值,也就是此時的 num ,然后將 send()里的參數傳給 yield num,進而賦值給 temp

更多關于Python相關內容可查看本站專題:《Python數據結構與算法教程》、《Python Socket編程技巧總結》、《Python函數使用技巧總結》、《Python字符串操作技巧匯總》及《Python入門與進階經典教程》

希望本文所述對大家Python程序設計有所幫助。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

娄烦县| 南丹县| 巴塘县| 蓬安县| 理塘县| 灌南县| 炉霍县| 阿拉善右旗| 封丘县| 禹城市| 手机| 曲松县| 乌拉特中旗| 建德市| 湖南省| 浦北县| 虎林市| 雷山县| 东宁县| 屯昌县| 文成县| 都昌县| 青河县| 东城区| 隆尧县| 万山特区| 平湖市| 开远市| 英山县| 侯马市| 盐源县| 怀宁县| 丹凤县| 汝州市| 五家渠市| 崇明县| 新营市| 尉氏县| 革吉县| 南宫市| 无锡市|