python-13-迭代器,生成器,協程
阿新 • • 發佈:2018-12-22
列表,字典,字串,元祖都是可迭代物件(Iterable),這就意味著它們是可以使用 for迴圈 進行遍歷。
檢測是否是可迭代物件的方法 isinstance()
from collections import Iterable result=isinstance([1,2],Iterable) print('列表',result) result=isinstance((1,2),Iterable) print('元祖',result) result=isinstance({1:'2'},Iterable) print('字典',result) result=isinstance('sss',Iterable) print('字串型',result) result=isinstance(100,Iterable) print('int型',result) 列表 True 元祖 True 字典 True 字串型 True int型 False
製作一個迭代器,需要包含 iter()函式與next()函式,如下:
from collections import Iterable
class my_iterable():
def __iter__(self):
pass
def __next__(self):
pass
ii=my_iterable()
result=isinstance(ii,Iterable)
print(result)
True
當擁有了這兩個函式,便被承認為一個可迭代物件
自定義一個迭代器
1、MyList類
class MyList(object):
# 1)初始化方法
def init
# 定義例項屬性,儲存資料 self.items = [] # 2)__iter__() 方法,對外提供迭代器 def __iter__(self): # 建立MyListIterator 物件 mylist_iterator = MyListIterator(self.items) # 返回迭代器 return mylist_iterator # 3)addItem() 方法,用來新增資料 def addItem(self, data): # 追加儲存資料 self.items.append(data) print(self.items)
2、自定義迭代器類:MyListIterator
class MyListIterator(object):
# 1) 初始化方法
def __init__(self, items):
# 定義例項屬性,儲存MyList類傳遞過來的items
self.items = items
# 記錄迭代器迭代的位置
self.current_index = 0
# 2)迭代器方法 __iter__()
def __iter__(self):
pass
# 3) 獲取下一個元素值的方法 __next__()
# next(mylist_iterator) 就會呼叫 __next__() 方法
def __next__(self):
# 1、 判斷當前的下標是否越界
if self.current_index < len(self.items):
# 1)根據下標獲取下標對應的元素值
data = self.items[self.current_index]
# 2)下標位置 +1
self.current_index += 1
# 3)返回下標對應的資料
return data
# 如果越界,直接丟擲異常
else:
# raise 用於主動丟擲異常
# StopIteration 停止迭代
raise StopIteration
if __name__ == '__main__':
# 1、建立自定義列表物件
mylist = MyList()
mylist.addItem("張飛")
mylist.addItem("關羽")
mylist.addItem("班長")
mylist.addItem("xxxxx")
# 遍歷
# 1) iter(mylist) 獲取 mylist物件的迭代器 --> MyList --> __iter__()
# 2)next(迭代器) 獲取下一個值
# 3)捕獲異常
# for value in mylist:
# print("name:", value)
mylist_iterator = iter(mylist)
# value = next(mylist_iterator)
# print(value)
#
# value = next(mylist_iterator)
# print(value)
3.生成器
生成器是一種特殊的迭代器,它更加便捷
建立生成器的第一種方法
1 . 列表推導式建立法(將列表推導式外面的 [] 變成())
kk=(aa*2 for aa in range(20))
2 . yeid建立
def work1():
yield 10 # 程式執行到yield語句的時候,程式暫停,返回yield後面表示式的值,在下一次呼叫的時候,從yield語句暫停的地方繼續執行
yield 100
kk=work1()
value=next(kk)
print(value)
4 . 協程
從技術的⻆度來說,“協程就是你可以暫停執⾏的函 數”。如果你把它理解成“就像⽣成器⼀樣”,那麼你就想對了。
協程存在的意義:對於多執行緒應⽤,CPU通過切⽚的⽅式來切換執行緒間的執⾏,執行緒切換時需要 耗時(儲存狀態,下次繼續)。協程,則只使⽤⼀個執行緒(單執行緒),在⼀個執行緒中規定某個程式碼塊 執⾏順序
①第一種協程方式
import time
def work1():
while True:
print('正在執行work1')
yield #執行大yield會暫停並儲存當前狀態,隨即去處理work2
time.sleep(0.5) #加時間延遲方便觀察
def work2():
while True:
print('正在執行work2')
yield #執行大yield會暫停並儲存當前狀態,隨即去處理work1
time.sleep(0.5)
if __name__ == '__main__':
w1 = work1()
w2 = work2()
while True:
next(w1)
next(w2)
②第二種協程方式
import time
from greenlet import greenlet
def work1():
while True:
print('正在執行work1')
time.sleep(0.5)
w2.switch()
def work2():
while True:
print('正在執行work2')
time.sleep(0.5)
w1.switch()
if __name__ == '__main__':
w1=greenlet(work1)
w2=greenlet(work2)
w1.switch()
③第三種協程方式(常用重要必記)
import time
import gevent #gevent 可以自動識別耗時程式碼然後切換到另一個任務
from gevent import monkey
monkey.patch_all() # 破解所有未識別的命令
def work1():
while True:
print('正在執行work1...')
time.sleep(0.3)
def work2():
while True:
print('正在執行work2...')
time.sleep(0.3)
if __name__ == '__main__':
# 指派任務
g1=gevent.spawn(work1) # gevent.spawn(函式名,引數1,引數2,引數3....)
g2=gevent.spawn(work2)
g1.join() # join 阻塞,讓主程序等待協程執行。
g2.join()