迭代器

一 .迭代器

1.1 可迭代對象

1.1.1 可迭代對象定義

對於迭代器來講,咱們更熟悉的應該是可迭代對象,以前不管是源碼仍是講課中或多或少咱們提到過可迭代對象這個詞。以前爲了便於你們理解可迭代對象,可能解釋的不是很正確,因此今天咱們正式的聊一聊什麼是可迭代對象。從字面意思來講,咱們先對其進行拆解:什麼是對象?Python中一切皆對象,以前咱們講過的一個變量,一個列表,一個字符串,文件句柄,函數名等等均可稱做一個對象,其實一個對象就是一個實例,就是一個實實在在的東西。那麼什麼叫迭代?其實咱們在平常生活中常常遇到迭代這個詞兒,更新迭代等等,迭代就是一個重複的過程,可是不能是單純的重複(若是隻是單純的重複那麼他與循環沒有什麼區別)每次重複都是基於上一次的結果而來。好比你爹生你,你生你爹,哦不對,你生你兒子,你兒子生你孫子等等,每一代都是不同的;還有你使用過得app,微信,抖音等,隔一段時間就會基於上一次作一些更新,那麼這就是迭代。可迭代對象從字面意思來講就是一個能夠重複取值的實實在在的東西。微信

那麼剛纔咱們是從字面意思分析的什麼是可迭代對象,到目前爲止咱們接觸到的可迭代對象有哪些呢?app

str list tuple dic set range 文件句柄等,那麼int,bool這些爲何不能稱爲可迭代對象呢?雖然在字面意思這些看着不符合,可是咱們要有必定的判斷標準或者規則去判斷該對象是否是可迭代對象。函數

在python中,但凡內部含有iter方法的對象,都是可迭代對象工具

1.1.2 查看對象內部方法

該對象內部含有什麼方法除了看源碼還有什麼其餘的解決方式麼?固然有了, 能夠經過dir() 去判斷一個對象具備什麼方法code

s1 = 'alex'
print(dir(s1))

dir()會返回一個列表,這個列表中含有該對象的以字符串的形式全部方法名。這樣咱們就能夠判斷python中的一個對象是否是可迭代對象了:對象

s1 = 'alex'
i = 100
print('__iter__' in dir(i))  # False
print('__iter__' in dir(s1))  # True

1.1.3 小結:

從字面意思來講:可迭代對象就是一個能夠重複取值的實實在在的東西。索引

從專業角度來講:但凡內部含有__iter__方法的對象,都是可迭代對象。內存

可迭代對象能夠經過判斷該對象是否有__iter__方法來判斷。utf-8

可迭代對象的優勢:

能夠直觀的查看裏面的數據。

可迭代對象的缺點:

1.佔用內存。

2.可迭代對象不能迭代取值(除去索引,key之外)。

那麼這個缺點有人就提出質疑了,即便拋去索引,key之外,這些我能夠經過for循環進行取值呀!對,他們均可以經過for循環進行取值,其實for循環在底層作了一個小小的轉化,就是先將可迭代對象轉化成迭代器,而後在進行取值的。那麼接下來,咱們就看看迭代器是個什麼鬼。

1.2 迭代器

1.2.1 迭代器的定義

從字面意思來講迭代器,是一個能夠迭代取值的工具,器:在這裏當作工具比較合適。

從專業角度來講:迭代器是這樣的對象:實現了無參數的__next__方法,返回序列中的下一個元素,若是沒有元素了,那麼拋出StopIteration異常.python中的迭代器還實現了__iter__方法,所以迭代器也能夠迭代。 出自《流暢的python》

那麼對於上面的解釋有一些超前,和難以理解,不用過於糾結,咱們簡單來講:**在python中,內部含有__Iter__方法而且含有__next__方法的對象就是迭代器。**

1.2.2 如何判斷該對象是不是迭代器

ok,那麼咱們有了這個定義,咱們就能夠判斷一些對象是否是迭代器或者可迭代對象了了,請判斷這些對象:str list tuple dict set range 文件句柄 哪一個是迭代器,哪一個是可迭代對象:

o1 = 'alex'
o2 = [1, 2, 3]
o3 = (1, 2, 3)
o4 = {'name': '太白','age': 18}
o5 = {1, 2, 3}
f = open('file',encoding='utf-8', mode='w')
print('__iter__' in dir(o1))  # True
print('__iter__' in dir(o2))  # True
print('__iter__' in dir(o3))  # True
print('__iter__' in dir(o4))  # True
print('__iter__' in dir(o5))  # True
print('__iter__' in dir(f))  # True

print('__next__' in dir(o1))  # False
print('__next__' in dir(o2))  # False
print('__next__' in dir(o3))  # False
print('__next__' in dir(o4))  # False
print('__next__' in dir(o5))  # False
print('__next__' in dir(f))  # True
f.close()

經過以上代碼能夠驗證,以前咱們學過的這些對象,只有文件句柄是迭代器,剩下的那些數據類型都是可迭代對象。

1.2.3 可迭代對象如何轉化成迭代器:

l1 = [1, 2, 3, 4, 5, 6]
obj = l1.__iter__()
# <list_iterator object at 0x000002057FE1A3C8>
# 或
obj = iter(l1)
print(obj)
# <list_iterator object at 0x102cc67f0>

1.2.4 迭代器取值:

可迭代對象是不能夠一直迭代取值的(除去用索引,切片以及Key),可是轉化成迭代器就能夠了,迭代器是利用__next__()進行取值:

l1 = [1, 2, 3,]
obj = l1.__iter__()  # 或者 iter(l1)
# print(obj)  # <list_iterator object at 0x000002057FE1A3C8>
ret = obj.__next__()
print(ret)
ret = obj.__next__()
print(ret)
ret = obj.__next__()
print(ret)
ret = obj.__next__()  # StopIteration
print(ret)
# 迭代器利用next取值:一個next取對應的一個值,若是迭代器裏面的值取完了,還要next,
# 那麼就報StopIteration的錯誤。

1.2.5 while模擬for的內部循環機制:

剛纔咱們提到了,for循環的循環對象必定要是可迭代對象,可是這不意味着可迭代對象就能夠取值,由於for循環的內部機制是:將可迭代對象轉換成迭代器,而後利用next進行取值,最後利用異常處理處理StopIteration拋出的異常。

l1 = [1, 2, 3, 4, 5, 6]
# 1 將可迭代對象轉化成迭代器
obj = iter(l1)
# 2,利用while循環,next進行取值
while 1:
    # 3,利用異常處理終止循環
    try:
        print(next(obj))
    except StopIteration:
        break

1.2.6 小結:

從字面意思來講:迭代器就是能夠迭代取值的工具。

從專業角度來講:在python中,內部含有__Iter__方法而且含有__next__方法的對象就是迭代器。

迭代器的優勢:

節省內存。 迭代器在內存中至關於只佔一個數據的空間:由於每次取值都上一條數據會在內存釋放,加載當前的此條數據。

惰性機制。 next一次,取一個值,毫不過多取值。

有一個迭代器模式能夠很好的解釋上面這兩條:迭代是數據處理的基石。掃描內存中放不下的數據集時,咱們要找到一種惰性獲取數據項的方式,即按需一次獲取一個數據項。這就是迭代器模式。

迭代器的缺點:

不能直觀的查看裏面的數據。

取值時不走回頭路,只能一直向下取值。

l1 = [1, 2, 3, 4, 5, 6]
obj = iter(l1)

for i in range(2):
    print(next(obj))

for i in range(2):
    print(next(obj))

1.3 可迭代對象與迭代器對比

咱們今天比較深刻的瞭解了可迭代對象與迭代器,接下來咱們說一下這二者之間比較與應用:

可迭代對象:

是一個私有的方法比較多,操做靈活(好比列表,字典的增刪改查,字符串的經常使用操做方法等),比較直觀,可是佔用內存,並且不能直接經過循環迭代取值的這麼一個數據集。

應用:當你側重於對於數據能夠靈活處理,而且內存空間足夠,將數據集設置爲可迭代對象是明確的選擇。

迭代器:

是一個很是節省內存,能夠記錄取值位置,能夠直接經過循環+next方法取值,可是不直觀,操做方法比較單一的數據集。

應用:當你的數據量過大,大到足以撐爆你的內存或者你以節省內存爲首選因素時,將數據集設置爲迭代器是一個不錯的選擇。(可參考爲何python把文件句柄設置成迭代器)。

相關文章
相關標籤/搜索