一、可迭代对象
介绍:可迭代对像一般可以用for循环进行遍历
- 可迭代对象判断法
from collections import Iterable
l = [11,22,33]
isinstance(l,Iterable) # 返回布尔型数值
- 可迭代对象满足的条件
此对象中必须含有__iter__方法
二、迭代器 - 迭代器判断方法
①此对象必须具有__iter__方法
②__iter__方法的返回值必须是一个具有__iter__和__next__方法的对象,实际上是返回一个迭代器对象。
总结
①迭代器一定是可迭代对象
②可迭代对象不一定是迭代器
class MyIterator(object):
"""自定义的一个迭代器"""
def __init__(self, mylist):
self.mylist = mylist
# current用来记录当前访问到的位置
self.current = 0
def __next__(self):
if self.current < len(self.mylist.items):
item = self.mylist.items[self.current]
self.current += 1
return item
else:
raise StopIteration
def __iter__(self):
return self #此对象本身既是可迭代对象,又是迭代器
-
for循环遍历的本质
每当for循环遍历依次,就会自动调用可迭代对象中的__iter__方法,此方法返回一个迭代器,然后再紧接着自动调用迭代器中的__next__方法,而__next__方法就会将可迭代对象中的值依次返回,每对可迭代对象遍历一次,迭代器中的__next__就将可迭代对象中的值返回一次
二、生成器
介绍: 生成器也是一种特殊的迭代器,只不过实现方式不同 -
实现
方式一:列表生成式
l = (x**2 for x in range(10)) #此时l就是一个生成器,可以进行for循环遍历或next()函数获取它的值
方式二:简单来说:只要在def中有yield关键字的 就称为 生成器
def fibonacci(all_num):
a,b = 0,1
cur_num = 0
while cur_num < all_num:
yield a
a,b = b, a+b
cur_num += 1
fibo = fibonacci(10)
for i in range(10):
ret = next(fibo)
print(ret)
注
①生成器和迭代器均减少内存,存储的是产生数据的方式,而不是产生数据的结果
②yiled关键字起到暂停生成器函数的程序,当执行next(迭代器名)时,意味着开启迭代器,并将yield 后面的值传递给next(迭代器名),当再次对迭代器对象调用next(迭代器名)函数时,程序将继续从yield后面的程序运行
③只有yield时默认传递值为None
三、多协程
*介绍:*多协程主要是利用协程中的延时时间,来进行其他协程的运行
- 实现方式
方式一:yield方式实现
import time
def work1():
while True:
print("----work1---")
yield
time.sleep(0.5)
def work2():
while True:
print("----work2---")
yield #延时操作
time.sleep(0.5) #延时操作
def main():
w1 = work1()
w2 = work2()
while True:
next(w1) # 执行协程w1 遇到yield,暂停协程w1
next(w2) #执行协程w2
if __name__ == "__main__":
main()
方式二:greenlet实现
from greenlet import greenlet
# 首先需要先下载此模块
import time
def test1():
while True:
print "---A--"
# 手动切换到协程test2运行
gr2.switch()
time.sleep(0.5)
def test2():
while True:
print "---B--"
#手动切换到test1运行
gr1.switch()
time.sleep(0.5)
if __name__ == '__main__':
#创建多协程
gr1 = greenlet(test1)
gr2 = greenlet(test2)
#首先切换到gr1中运行
gr1.switch()
方式三:gevent实现
from gevent import monkey
import gevent
import random
import time
monkey.patch_all() #打补丁
def work1():
while True:
print("----work1---")
time.sleep(random.random())
def work2():
while True:
print("----work2---")
time.sleep(random.random())
#依次添加协程
g1 = gevent.spawn(coroutine_work, "work1"),
g2 = gevent.spawn(coroutine_work, "work2")
g1.join()
g2.join()
#一次性添加协程
gevent.joinall([
gevent.spawn(coroutine_work, "work1"),
gevent.spawn(coroutine_work, "work2")
])
注
①打补丁的作用是将协程中所有的延时操作替换成以gevent方式进行的延时操作,因为此模块实现的多协程中,延时操作必须要用gevent方式延时(例如:time.sleep(5)–gevent.sleep(5))
②多协程实现的多任务实际是并发,而不是并行,类似于cpython中的多线程实现的多任务