chunjiekid 2019-07-01
协程
一,迭代器iterable 能实现一定的数据,但是又不会占用很大的空间,协程切换任务资源小,效率高。
如何判断某一类型是否可以迭代
from collections import Iterable print(isinstance([11,2,3], Iterable))
python2是如下实现的,python3中将range改成了xrange
range(2000)生成2000个值的结果,会占用很大的内存空间
xrange(2000)是指生成2000个值的方式,占用很小的空间。
如果一个对象是迭代器,那么一定可以迭代,如果一个对象可以迭代,但不一定是迭代器。
迭代器对象必须要有__iter__和__next__方法。
如果数据量很大的情况下,最好使用创建迭代器的方式来节省内存空间。
eg:
class Fibo(object): def __init__(self, all_num): self.all_num = all_num self.current_num = 0 self.a = 0 self.b = 1 def __iter__(self): return self def __next__(self): if self.current_num < self.all_num: ret = self.a self.a, self.b = self.b, self.a + self.b self.current_num += 1 return ret else: raise StopIteration fibo = Fibo(20) for temp in fibo: print(temp)
二, 生成器generator
生成器是一种特殊的迭代器,可以让函数暂停执行。所以可以利用生成器实现多任务。
生成迭代器有两种方式:
def fibo(max_num): a, b = 0, 1 current_num = 0 while current_num < max_num: yield a a, b = b, a + b current_num += 1 fi = fibo(20) while True: try: ret = next(fi) print(ret) except: break
三,协程greenlet、gevent完成多任务
gevent是协程最常用的一种方式。当线程在等待执行浪费的时间,可以用协程来解决。协程会在等待时间去执行别的方法。
eg:协程的实际使用
def download_pic(img_name, img_url): request = urllib.request.urlopen(img_url) img_content = request.read() with open(img_name, 'wb') as f: f.write(img_content) def main(): gevent.joinall([ gevent.spawn(download_pic, '1.jpg', 'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1556006133066&di=6c4ea03a666b333328d59163b8137de9&imgtype=0&src=http%3A%2F%2Fattach.bbs.miui.com%2Fforum%2F201408%2F27%2F103420lzrq3jcimigfjmuw.jpg'), gevent.spawn(download_pic, '2.jpg', 'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1556006133066&di=1f17489eb4f7fd3ce4f16c2365fab82a&imgtype=0&src=http%3A%2F%2Fb-ssl.duitang.com%2Fuploads%2Fblog%2F201511%2F08%2F20151108150337_tu32m.jpeg') ]) if __name__ == '__main__': main()