迭代器减少了内存空间的同时可以实现循环,
生成器可以让一个函数暂停执行,什么时候又想开始执行的时候继续恢复到上一次的状态开始执行,第一次可以通过next()函数启动,第二次及其以上可以通过send()启动
进程、线程、协程对比
请仔细理解如下的通俗描述
有一个老板想要开个工厂进行生产某件商品(例如剪子)
他需要花一些财力物力制作一条生产线,这个生产线上有很多的器件以及材料这些所有的 为了能够生产剪子而准备的资源称之为:进程
只有生产线是不能够进行生产的,所以老板的找个工人来进行生产,这个工人能够利用这些材料最终一步步的将剪子做出来,这个来做事情的工人称之为:线程
这个老板为了提高生产率,想到3种办法:
在这条生产线上多招些工人,一起来做剪子,这样效率是成倍増长,即单进程 多线程方式
老板发现这条生产线上的工人不是越多越好,因为一条生产线的资源以及材料毕竟有限,所以老板又花了些财力物力购置了另外一条生产线,然后再招些工人这样效率又再一步提高了,即多进程 多线程方式
老板发现,现在已经有了很多条生产线,并且每条生产线上已经有很多工人了(即程序是多进程的,每个进程中又有多个线程),为了再次提高效率,老板想了个损招,规定:如果某个员工在上班时临时没事或者再等待某些条件(比如等待另一个工人生产完谋道工序 之后他才能再次工作) ,那么这个员工就利用这个时间去做其它的事情,那么也就是说:如果一个线程等待某些条件,可以充分利用这个时间去做其它事情,其实这就是:协程方式
简单总结
进程是资源分配的单位
线程是操作系统调度的单位
进程切换需要的资源很最大,效率很低
线程切换需要的资源一般,效率一般(当然了在不考虑GIL的情况下)
协程切换任务资源很小,效率高
多进程、多线程根据cpu核数不一样可能是并行的,但是协程是在一个线程中 所以是并发
具体可以参照代码:
迭代器.py
#__author:bo
#date:2019/4/11
import time
from collections import Iterable
from collections import Iterator
class Classmate(object):
def __init__(self):
self.name=list() # 定义一个 name 属性,存放 name
def add(self,name):
self.name.append(name)
def __iter__(self): # 如果要是一个可迭代对象,必须实现 ——iter__ 这个方法
# __iter__ 防范必须返回一个对象的引用,这个对象的 next 返回的是什么,则 for 循环中取到的就是什么
return ClassIterator(self) # 如果要称为一个迭代器,必须在 __iter__ 方法中返回一个迭代器对象
class ClassIterator(object):
'''如果要是一个迭代器对象,必须要有 __iter__ __next__ 这两个方法'''
def __init__(self,obj):
self.obj=obj
self.num=0
def __iter__(self):
pass
def __next__(self):
if self.num<len(self.obj.name): # 防止下标越界
res=self.obj.name[self.num]
self.num+=1
return res
else:
raise StopIteration # 如果发生异常,则直接停止迭代,即停止for循环的部分
classmate=Classmate()
classmate.add("111")
classmate.add("222")
classmate.add("333")
for temp in classmate:
print(temp)
time.sleep(1)
#__author:bo
#date:2019/4/11
import time
from collections import Iterable
from collections import Iterator
class Classmate(object):
def __init__(self):
self.name=list() # 定义一个 name 属性,存放 name
self.num=0
def add(self,name):
self.name.append(name)
def __iter__(self): # 如果要是一个可迭代对象,必须实现 ——iter__ 这个方法
# __iter__ 防范必须返回一个对象的引用,这个对象的 next 返回的是什么,则 for 循环中取到的就是什么
return self # 如果要称为一个迭代器,必须在 __iter__ 方法中返回一个迭代器对象
def __next__(self):
if self.num < len(self.name): # 防止下标越界
res = self.name[self.num]
self.num += 1
return res
else:
raise StopIteration # 如果发生异常,则直接停止迭代,即停止for循环的部分
# 将一个类改造成为一个迭代器
# 总结 :迭代器一定是可迭代对象,但是可迭代对象不一定是迭代器,
classmate=Classmate()
classmate.add("111")
classmate.add("222")
classmate.add("333")
for temp in classmate:
print(temp)
time.sleep(1)
#__author:bo
#date:2019/4/11
import time
from collections import Iterable
from collections import Iterator
class Fibonacci(object):
def __init__(self,all_nums):
self.name=list() # 定义一个 name 属性,存放 name
self.current_num=0
self.all_num=all_nums
self.a=0
self.b=1
def add(self,name):
self.name.append(name)
def __iter__(self): # 如果要是一个可迭代对象,必须实现 ——iter__ 这个方法
# __iter__ 防范必须返回一个对象的引用,这个对象的 next 返回的是什么,则 for 循环中取到的就是什么
return self # 如果要称为一个迭代器,必须在 __iter__ 方法中返回一个迭代器对象
def __next__(self):
if self.current_num<self.all_num:
res = self.a
self.a,self.b=self.b,self.a+self.b
self.current_num+=1
return res
else:
raise StopIteration # 如果发生异常,则直接停止迭代,即停止for循环的部分
fibo=Fibonacci(10)
for num in fibo:
print(num)
# __author:bo
# date:2019/4/11
# 只要添加了 yield 就成了生成器,生成器一定是迭代器
def create_num(all_num):
a, b = 0, 1
current_num = 0
while current_num < all_num:
# print(a)
yield a # 如果一个函数中有 yield ,则这个函数不是函数,而是一个生成器模板
a, b = b, a + b
current_num += 1
obj1 = create_num(10) # 创建一个生成器对象,而不是调用函数
res1=next(obj1)
print("obj1 res1",res1)
obj2 = create_num(10) # 创建一个生成器对象,而不是调用函数
res3=next(obj2)
print("obj2 res3",res3)
res4=next(obj2)
print("obj2 res4",res4)
res2=next(obj1)
print("obj1 res2",res2) # 创建的两个迭代器不重复,
# 当进行for循环开始的时候,才开始执行 create_num ,第一次到 yield 那儿停下,
# 将 yield 后边的值返回给 num ,然后开始 print,当下一次 for 循环的时候,从
# create_num的yield 的的下一行开始,一直这样循环,直到退出while循环
# for num in obj:
# print(num)
# __author:bo
# date:2019/4/11
# 只要添加了 yield 就成了生成器,生成器一定是迭代器
def create_num(all_num):
a, b = 0, 1
current_num = 0
while current_num < all_num:
# print(a)
yield a # 如果一个函数中有 yield ,则这个函数不是函数,而是一个生成器模板
a, b = b, a + b
current_num += 1
return "已经结束" # 如果想得到这个返回值,必须用 excepton 中的 value 来取
obj = create_num(20) # 创建一个生成器对象,而不是调用函数
while True:
try:
res=next(obj) # 生成器可以用 next 来启动
print(res)
except StopIteration as res: # 当发生异常的时候停止迭代
print(res.value) # 想要得到生成器的返回值,来取迭代完成之后的返回值
break
# __author:bo
# date:2019/4/11
def create_num(all_num):
a, b = 0, 1
current_num = 0
while current_num < all_num:
ret=yield a
print(">>>ret>>>",ret)
a, b = b, a + b
current_num += 1
return "已经结束"
obj=create_num(10)
res=next(obj)
print(res) # 这种 next 方式不能往里面传递参数
# 如果想要用 send 不要把 send 放在第一位,第一位一定是 next ,因为第一次没有东西接收 send 传递的参数
res2=obj.send(None) # send 可以往里面传递参数, send 里面传递的值是下一次 yield 的值
print(res2)