一、迭代器
\qquad
1、解释:迭代器(iterator)是一种对象,它能够用来遍历标准模板库容器中的部分或全部元素,每个迭代器对象代表容器中的确定的地址。简单来说可迭代对象是可以直接使用for循环的对象。迭代器
\qquad
2、判断数据类型是否可迭代。
\qquad
判断某一数据类型是否可迭代,可使用isinstance()判断一个对象是否为可迭代对象。
from collections import Iterable
a = isinstance([],Iterable)
b = isinstance((),Iterable)
c = isinstance("asdfg",Iterable)
d = isinstance(100,Iterable)
print([a,b,c,d])
\qquad
代码结果解释:最后输出的结果是[True,True,True,False],说明列表,数组,字符串都属于可迭代对象,而数值不属于可迭代对象。
\qquad
可以被next()函数调用并不断返回下一个值的对象称为迭代器。可以使用isinstance()判断一个对象是否为迭代器。
from collections import Iterator
a = isinstance((x for x in range(10)),Iterator)
b = isinstance([],Iterator)
c = isinstance((),Iterator)
d = isinstance("asdf",Iterator)
print([a,b,c,d])
\qquad
运行结果及解释:运行结果为[True,Flase,False,False],说明列表,数组,字符串属于可迭代对象,但不是迭代器。
\qquad
3、实现可迭代对象
import time
class Classmate(object):
def __init__(self):
self.names = list()
def add(self,name):
self.names.append(name)
def __iter__(self):
return classIterator(self)
class classIterator(object):
def __init__(self,obj):
self.obj = obj
self.corrent_num = 0
def __iter__(self):
pass
def __next__(self):
if self.corrent_num<len(self.obj.names):
ret = self.obj.names[self.corrent_num]
self.corrent_num+=1
return ret
else:
raise StopIteration
classmate = Classmate()
classmate.add("wanger")
classmate.add("zhangsan")
classmate.add("lisi")
for name in classmate:
print(name)
time.sleep(1)
\qquad 迭代器的优点:只提供迭代的方式,在迭代的时候才调用迭代的数据,节省了空间。
二、生成器
\qquad
1、定义:生成器是一次生成一个值的特殊类型函数。可以将其视为可恢复函数。调用该函数将返回一个可用于生成连续 x 值的生成器。简单的说就是在函数的执行过程中,yield语句会把你需要的值返回给调用生成器的地方,然后退出函数,下一次调用生成器函数的时候又从上次中断的地方开始执行,而生成器内的所有变量参数都会被保存下来供下一次使用。生成器是一种特殊的迭代器。
\qquad
2、创建生成器的方法
\qquad
方法一:列表生成式的 [ ] 改成( )
num = [x for x in range(10)]
num
nums = (x for x in range(10))
nums
\qquad
运行结果及解释:num是一个列表,nums是一个生成器。
\qquad
方法二:在定义函数时使用yeild。
def fib(num):
num1,num2 = 0,1
current_num = 0
while current_num<num:
#如果一个函数出现yield,那么这个函数不再时一个函数,而是一个生成器mu'ba
yield num1
num1,num2 = num2,num1+num2
current_num+=1
#调用函数时,发现函数中有yield,则不再是调用函数,而是创建一个生成器
fib(10)
三、使用协程实现多任务
$\qquad$1、使用yield完成多任务
import time
def task1():
while True:
print("---1---")
time.sleep(1)
yield
def task2():
while True:
print("---2---")
time.sleep(1)
yield
def main():
t1 = task1()
t2 = task2()
while True:
next(t1)
next(t2)
if __name__ == "__main__":
main()
$\qquad$2、使用greenlet完成多任务
from greenlet import greenlet
import time
def task1():
while True:
print("---1---")
gr2.switch()
time.sleep(1)
def task2():
while True:
print("---2---")
gr1.switch()
time.sleep(1)
gr1 = greenlet(task1)
gr2 = greenlet(task2)
gr1.switch()
\qquad 3、使用gevent完成多任务
import gevent
def f(n):
for i in range(n):
print(gevent.getcurrent(),i)
g1 = gevent.spawn(f,5)
g2 = gevent.spawn(f,5)
g3 = gevent.spawn(f,5)
g1.join()
g2.join()
g3.join()
\qquad 代码运行后结果是并不是实行多任务,而是一个任务一个任务地完成。所以需要延时操作才能完成多任务,但gevent所有地延时操作必须使用gevent模块里的延时操作。或者创造补丁,使得所有延时操作自动转换成gevent模块的延时操作。
import gevent
import time
from gevent import monkey
monkey.patch_all()
def f(n):
for i in range(n):
print(gevent.getcurrent(),i)
time.sleep(0.5)
g1 = gevent.spawn(f,5)
g2 = gevent.spawn(f,5)
g3 = gevent.spawn(f,5)
g1.join()
g2.join()
g3.join()