python 全棧開發,Day13(迭代器,生成器)

1、迭代器

python 一切皆對象python

能被for循環的對象就是可迭代對象git

可迭代對象: str,list,tuple,dict,set,range程序員

迭代器: f1文件句柄面試

 

dir打印該對象的全部操做方法api

s = 'python'
print(dir(s))

執行輸出:ssh

['__add__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__gt__', '__hash__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'capitalize', 'casefold', 'center', 'count', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'format_map', 'index', 'isalnum', 'isalpha', 'isdecimal', 'isdigit', 'isidentifier', 'islower', 'isnumeric', 'isprintable', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'maketrans', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']ide

 

什麼是可迭代對象:內部含有__iter__方法的對象就叫作可迭代對象
可迭代對象就遵循可迭代協議。函數

如何判斷 兩種方式優化

第一種:spa

s = 'python'
print('__iter__' in dir(s))

執行輸出:

True

 

第二種:

from collections import Iterable
l = [1, 2, 3, 4]
print(isinstance(l, Iterable))

執行輸出:

True

 

from collections import Iterable
l = [1, 2, 3, 4]
print(type(l))
print(isinstance(l,list))

執行輸出:

<class 'list'>
True

 


type只能判斷是什麼類型

isinstance判斷方面更廣,不只能判斷類型,還能判斷是否可迭代

 

迭代器

可迭代對象轉化成迭代器:可迭代對象.__iter__() --->迭代器
迭代器不只含有__iter__,還含有__next__。遵循迭代器協議。

l1 = [1,2,3]
l1_obj = l1.__iter__()  # 迭代器
print(l1_obj)

執行輸出:

<list_iterator object at 0x000001987D5EB668>

表示它是一個列表迭代器對象

 

l1 = [1,2,3]
l1_obj = l1.__iter__()  # 迭代器
print('__iter__' in  dir(l1_obj)) #是否含有__iter__方法
print('__next__' in  dir(l1)) #是否含有__next__方法
print('__next__' in  dir(l1_obj))

執行輸出:

True
False
True

 

從結果中,能夠看出l1_obj是同時含有__iter__和__next__的對象,因此它是迭代器

 

迭代器使用__next__獲取一個值

l1 = [1,2,3]
l1_obj = l1.__iter__()  # 迭代器
print(l1_obj.__next__()) #獲取一個元素
print(l1_obj.__next__())
print(l1_obj.__next__())
print(l1_obj.__next__())

執行報錯:

1
Traceback (most recent call last):
2
3
File "E:/python_script/day13/迭代器.py", line 9, in <module>
print(l1_obj.__next__())
StopIteration

多取了一個,就會報錯,由於列表只有3個元素

 

使用for循環方式

l1 = [1,2,3]
l1_obj = l1.__iter__()  # 轉換爲迭代器
for i in l1_obj:
    print(i)

執行輸出:

1
2
3

 

for循環的內部機制,就是用__next__方法執行的。爲何沒有報錯呢?它內部有異常處理機制

總結:

 

僅含有__iter__方法的,就是可迭代對象
包含__iter__和__next__方法的,就是迭代器

 

判斷迭代器的2種方法:

第1種:

l1 = [1,2,3]
l1_obj = l1.__iter__()  # 轉換爲迭代器
print('__iter__' in  dir(l1_obj))

第2種:

l1 = [1,2,3]
l1_obj = l1.__iter__()  # 轉換爲迭代器
from collections import Iterator
print(isinstance(l1_obj, Iterator))

返回True,就表示它是的

 

迭代器的好處:
1,節省內存空間。
2,知足惰性機制。
3,不能反覆取值,不可逆。

 

不可逆,表示,已經取過的值,不能再次取,它只能取下一個。

 

for處理機制

l2 = [1, 2, 3, 4, 5, 6, 7, 8]
for i in l2:
    print(i)

1,將可迭代對象轉化成迭代器
2,內部使用__next__方法取值
3,運用了異常處理去處理報錯。

 

迭代器最大的好處,就是節省內存
好的程序員,會在內存優化方面考慮,好比迭代器。

 

使用while循環,指定用__next__方法遍歷列表

l2 = [1, 2, 3, 4, 5, 6, 7, 8]
l2_obj = l2.__iter__() #1.將可迭代對象轉化成迭代器
while True:
    try:
        i = l2_obj.__next__() #內部使用__next__方法取值
        print(i)
    except Exception: #運用了異常處理去處理報錯
        break

try裏面的代碼,出現報錯,不會提示紅色文字
Exception 能夠接收全部報錯,表示報錯的時候,該怎麼處理,這裏直接使用breck跳出循環

 

面試題:

使用whlie循環去遍歷一個有限對象

直接使用上述代碼便可。

 

2、生成器

 生成器:生成器本質上是迭代器

l = [1,2,3]
l.__iter__() 

#生成器的產生方式:
1,生成器函數構造。
2,生成器推導式構造。
3,數據類型的轉化。

 

def func1():
    print(111)
    print(222)
    print(333)
    return 666
print(func1())

執行輸出:

111
222
333
666

 

將函數轉換爲生成器

def func1():
    print(111)
    print(222)
    print(333)
    yield 666
g = func1()
print(g)

執行輸出:

<generator object func1 at 0x000001B4C369DE60>

 

第一:函數中只要有yield 那他就不是一個函數,而是一個生成器
第二:g稱做生成器對象。

 

迭代器,使用__next__取值

def func1():
    print(111)
    print(222)
    print(333)
    yield 666
g = func1()
print(g.__next__())
print(g.__next__()) 

執行報錯
一個__netxt__對應一個yield

 

好比生產10000套服裝

一個廠商直接生產出10000套了

def func1():
    for i in range(1,10001):
        print('ARMAIN服裝%d套' % i)
func1()

執行輸出:

...

ARMAIN服裝9998套
ARMAIN服裝9999套
ARMAIN服裝10000套

 

第二個廠商,先生產出50套,給老闆看

def func1():
    for i in range(1,10001):
        yield 'ARMAIN服裝%d套' % i
g = func1()
for i in range(1,51):
    print(g.__next__())

執行輸出:

...

ARMAIN服裝48套
ARMAIN服裝49套
ARMAIN服裝50套

 

最終老闆只要200套
先50套,再150套

def func1():
    for i in range(1,10001):
        yield 'ARMAIN服裝%d套' % i
g = func1()
for i in range(1,51):
    print(g.__next__())
#再執行150次,注意,它是從51開始的
for j in range(150):
    print(g.__next__())

以前生產10000套的....

 

對於列表而言,for循環是從開始
對於生成器而言,它是有指針的,__next__一次,指針向前一次。它不能從頭開始。
必須依次執行才行

生成器和迭代器的區別
迭代器: 有內置方法
生成器: 開發者自定義

 

send

def generator():
    print(123)
    content = yield 1
    print('=======',content)
    print(456)
    yield

g = generator()
ret = g.__next__()
print('***',ret)
ret = g.send('hello')   #send的效果和next同樣
print('***',ret)

執行輸出:

123
*** 1
======= hello
456
*** None

 

send 獲取下一個值的效果和next基本一致
只是在獲取下一個值的時候,給上一yield的位置傳遞一個數據
使用send的注意事項

   第一次使用生成器的時候 是用next獲取下一個值
   最後一個yield不能接受外部的值

 

next 和send 功能同樣,都是執行一次
send能夠給上一個yield賦值。

 

明日默寫內容:

 

1.什麼是可迭代對象,什麼是迭代器
答:
內部含有__iter__方法的對象就叫作可迭代對象
內部必須有__iter__方法和__next__方法的對象,叫作迭代器

2.可迭代對象如何轉化成迭代器
答:
轉化成迭代器:可迭代對象.__iter__() --->迭代器
例如

l1 = [1,2,3]
l1_obj = l1.__iter__()


3.迭代器如何取值
答:
迭代器使用__next__()方法

 

4.什麼是生成器?如何寫一個生成器?生成器怎麼取值?
答:
生成器,即生成一個容器。在Python中,一邊循環,一邊計算的機制,稱爲生成器。

#生成器示例

def fun1():
    yield 1

  

生成器使用__next__()方法取值,或者for循環

相關文章
相關標籤/搜索