面試題-python 什么是迭代器(Iterator)?


前言

python 里面有 3 大神器:迭代器,生成器,裝飾器。在了解迭代器之前,需弄清楚2個概念:
1.什么是迭代
2.什么是可迭代對象

迭代

如果給定一個list或tuple,我們可以通過for循環來遍歷這個list或tuple,這種遍歷我們稱為迭代(Iteration)
在Python中,迭代是通過for ... in來完成的。

"""
列表a中大於0的值,得到新的列表
"""
a = [1, -2, 3, -5, 7]

c = []
for i in a:
    if i > 0:
        c.append(i)
print(c)  # [1, 3, 7]

Iterable 可迭代對象

在python 里面 list、tuple、dict、set、str 這些基礎數據類型都是可以作用於for循環的。
可以使用 isinstance() 判斷一個對象是否是 Iterable 對象:

"""
isinstance 判斷實例類型
Iterable 可迭代對象
"""

from collections import Iterable

a = 12
print(isinstance(a, Iterable))
b = "abc"
print(isinstance(b, Iterable))
c = [1, 2, 3]
print(isinstance(c, Iterable))
d = (1, 2, 3)
print(isinstance(d, Iterable))
e = {1, 2, 3}
print(isinstance(e, Iterable))
f = {"key": 1}
print(isinstance(f, Iterable))

運行結果
False
True
True
True
True
True

除了上面的6種基礎的是可迭代的,還有一類是 生成器(generator),包括生成器和帶yield的 生成器函數

Iterator 迭代器

可以被 next() 函數調用並不斷返回下一個值的對象稱為迭代器:Iterator。
可以使用isinstance() 判斷一個對象是否是 Iterator 對象:

from collections import Iterable, Iterator

a = 12
print(isinstance(a, Iterator))
b = "abc"
print(isinstance(b, Iterator))
c = [1, 2, 3]
print(isinstance(c, Iterator))
d = (1, 2, 3)
print(isinstance(d, Iterator))
e = {1, 2, 3}
print(isinstance(e, Iterator))
f = {"key": 1}
print(isinstance(f, Iterator))
結果返回
False
False
False
False
False
False

list、dict、str雖然是可迭代對象 (Iterable),卻不是 迭代器 (Iterator), 可以使用 iter() 函數,變成迭代器

# 作者-上海悠悠 QQ交流群:717225969
# blog地址 https://www.cnblogs.com/yoyoketang/

from collections import Iterable, Iterator

b = "abc"
new_b = iter(b)

print(new_b)
print(isinstance(new_b, Iterator))

c = [1, 2, 3]
print(iter(c))
print(isinstance(iter(c), Iterator))

d = (1, 2, 3)
print(iter(d))
print(isinstance(iter(d), Iterator))

e = {1, 2, 3}
print(iter(e))
print(isinstance(iter(e), Iterator))

f = {"key": 1}
print(iter(f))
print(isinstance(iter(f), Iterator))

迭代器 iter() 和 next()

迭代器有兩個基本的方法:iter() 和 next()。
使用iter() 創建一個迭代器后,可以使用next() 輸出迭代器的下一個元素

a = [1, 2, 3, 4]
it = iter(a)    # 創建迭代器對象
print(next(it))   # 輸出迭代器的下一個元素

print(next(it))

輸出結果
1
2

也可以使用 for 來遍歷

a = [1, 2, 3, 4]
it = iter(a)    # 創建迭代器對象
for x in it:
    print(x, end=" ")
輸出結果
1 2 3 4 

如果用next() 函數取值,一直取到沒有了,那就會拋出"StopIteration" 異常

a = [1, 2, 3, 4]
it = iter(a)    # 創建迭代器對象

print(next(it))
print(next(it))
print(next(it))
print(next(it))
print(next(it))   # StopIteration

運行結果

1
2
3
4
Traceback (most recent call last):
  File "D:/xx.py", line 9, in <module>
    print(next(it))
StopIteration

如果用next()輸出全部值,可以加個try...expect

a = [1, 2, 3, 4]
it = iter(a)    # 創建迭代器對象
 
while True:
    try:
        print(next(it))
    except StopIteration:
        break

創建迭代器

把一個類作為一個迭代器使用需要在類中實現兩個方法 __iter__()__next__()
__iter__() 方法返回一個特殊的迭代器對象, 這個迭代器對象實現了__next__() 方法並通過 StopIteration 異常標識迭代的完成。
__next__() 方法(Python 2 里是 next())會返回下一個迭代器對象。
創建一個返回數字的迭代器,初始值為 1,逐步遞增 1:

class MyNumbers:

    def __iter__(self):
        self.a = 1
        return self

    def __next__(self):
        x = self.a
        self.a += 1
        return x

myclass = MyNumbers()
myiter = iter(myclass)
print(next(myiter))
print(next(myiter))
print(next(myiter))
輸出結果
1
2
3

StopIteration

StopIteration 異常用於標識迭代的完成,防止出現無限循環的情況,在 __next__() 方法中我們可以設置在完成指定循環次數后觸發 StopIteration 異常來結束迭代。

class MyNumbers:

    def __iter__(self):
        self.a = 1
        return self

    def __next__(self):
        if self.a <= 3:
            x = self.a
            self.a += 1
            return x
        else:
            raise StopIteration

myclass = MyNumbers()
myiter = iter(myclass)
print(next(myiter))
print(next(myiter))
print(next(myiter))
# 第4次會拋異常
print(next(myiter))

在 3 次迭代后停止執行

斐波那契數列

斐波那契數列指的是這樣一個數列 0, 1, 1, 2, 3, 5, 8, 13,特別指出:第0項是0,第1項是第一個1。從第三項開始,每一項都等於前兩項之和
求出小於100 的所有的斐波那契數列

# 作者-上海悠悠 QQ交流群:717225969
# blog地址 https://www.cnblogs.com/yoyoketang/


class MyNumbers:

    def __iter__(self):
        self.n1 = 0
        self.n2 = 1
        self.count = 1
        return self

    def __next__(self):
        self.n1, self.n2 = self.n2, self.count
        self.count = self.n1 + self.n2
        if self.count <= 100:
            return self.count
        else:
            raise StopIteration

myclass = MyNumbers()
myiter = iter(myclass)
while True:
    try:
        print(next(myiter), end=" ")
    except StopIteration:
        break

# 也可以用 for 遍歷輸出 
for i in myiter:
    print(i, end=" ")

輸出結果:2 3 5 8 13 21 34 55 89


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM