(protocol)的意思,其实协议是用来“规范/标准化”你“创造的东西”的。比如,你开天辟地的发明了一种东西叫做“我爱你却不能在一起”,你给小沛说:“小沛,给我发一个我爱你却不能在一起过来”,如果小沛不知道啥叫“我爱你却不能在一起”,那么小沛会直接懵逼的。这时候你就要定一个“协议”如下:
1, "我爱你却不能在一起"一共有10个字
2, "我爱你却不能在一起"开头和结尾都是"#"号 (占两个字)
3, "我爱你却不能在一起"最后二位是"bp"
4, 其他不限制
那么我们根据这个协议,可以很轻易的构造出“我爱你却不能在一起”来:#0629bp# 或者 #0819bp#
同样,我们根据这份协议,就可以用来检测你得到的是不是“我爱你却不能在一起”,#3141bp# -> 是,#1314bp!-> 不是
迭代(iteration)迭代就是重复的的既定的任务,直到完成。所以,为了完成迭代,我们需要一个迭代器!
迭代器协议 iterator protocol
从前有个人发明了迭代器,为了让大家明白什么是迭代器,他就写了这个协议,那么协议的内容简而言之就是一句话:如果一个对象包括一个叫"next"(python3 为__next__)的方法,那么这个对象就叫做“迭代器”。
可迭代协议 iterable protocol
在python中,为了使一个”对象“可迭代:
生成器generator1,这个迭代器必须同时包含另一个方法叫做“__iter__”
2,这个"__iter__"方法还得返回一个”迭代器“(可迭代)
生成器的出现,就是为了简化创建迭代器的繁杂,同时又要保证逻辑的清晰,说到底生成器就是为了更方便我们使用迭代器而生的,生成器的特性如下:
1, 生成器的样子就是一个普通的函数,只不过return关键词被yield取代了
2, 当调用这个“函数”的时候,它会立即返回一个迭代器,而不立即执行函数内容,直到调用其返回迭代器的next方法是才开始执行,直到遇到yield语句暂停。
3, 继续调用生成器返回的迭代器的next方法,恢复函数执行,直到再次遇到yield语句
4, 如此反复,一直到遇到StopIteration
看如下例子:
def gFun():
print('before wp')
yield 'wp'
print('after wp')
a = gFun() # 调用生成器函数,返回一个迭代器并赋给a
print(a) #
print(a.__next__())
# before wp# wp print(a.__next__())
# after wp# StopIteration
同时因为调用生成器函数返回的是一个迭代器,所以我们可以使用for..in语法糖对其进行迭代操作:
a = gFun()for x in a:
print(x)
迭代返回了before wp, wp, after wp
def gen():
for i in range(10):
yield i
复制代码
这里yield的作用就相当于return,这个函数就是顺序地返回[0,10)的之间的自然数,可以通过next()或使用for循环来遍历。
当程序遇到yield关键字时,这个生成器函数就返回了,直到再次执行了next()函数,它就会从上次函数返回的执行点继续执行,即yield退出时保存了函数执行的位置、变量等信息,再次执行时,就从这个yield退出的地方继续往下执行。
在Python中利用生成器的这些特点可以实现协程。协程可以理解为一个轻量级的线程,它相对于线程处理高并发场景有很多优势。
从 generator对象获取值
为了从 generator 对象获取值,我们可以使用 for loop、next() 或者 list() 方法。
for loop 方法:
def odd_numbers(n): for x in range(n): if (x % 2) == 1: yield x num = odd_numbers(10) for i in num: print(i) list()方法 def odd_numbers(n): for x in range(n): if (x % 2) == 1: yield x num = odd_numbers(10)for i in list(num): print(i) generator 对象只能被遍历一次 generator 对象只能被遍历一次,当我们再次使用时, generator 对象为空。 yield vs. return
包含 yield 的函数在被调用时,返回一个 generator 对象给调用者,只有在遍历对象时,函数的代码才会被执行。而函数中的 return 返回一个值给调用者。
总结:- 和 return 关键字返回一个值给调用者不同的是,包含 yield 关键字的函数返回一个 generator 对象给调用者。
- 返回的 generator 对象在使用过一次后便不再可以使用,如果要获取值,需要遍历 generator 对象。
- 可以使用 for loop、next() 或者 list() 方法从 generator 对象获取值。
- yield 和 return 的最大区别是,yield 返回一个 generator 给调用者,而 return 返回一个值给调用者。
- 使用 yield 时,不会将值存储在内存中,这在处理的数据量很大时,比较有优势。
- yield from 后面加上可迭代对象,可以把可迭代对象里的每个元素一个一个的 yield 出来,对比 yield 来说代码更加简洁,结构更加清晰。
协程是什么?
和 python 中的多线程(threading)一样,协程也是实现并发(concurrent)的一种方式,而在多线程中,各个线程之间何时切换、如何切换则是由系统自行处理,所以可能会造成一些不可控的现象发生,如中断了不该中断的重要线程或中途产生了不合理的数据等。而在协程中,不存在被中断一说,只有通过 yield 或 yield from 主动释放 CPU 资源,让步给其他协程,以此实现多线程的并发。



