Discuss / Python / 我想试试看解释这个生产消费的例子,教程里面解释得太粗糙看不懂

我想试试看解释这个生产消费的例子,教程里面解释得太粗糙看不懂

Topic source

壮丁宇素

#1 Created at ... [Delete] [Delete and Lock User]

1、produce(c)开始运行,首先c.send(None)会启动generator 也就是 consumer(),第一次运行yield得到的是空值(r=''),刚好符合if not n,consumer就结束(return)了。

2、produce继续往下执行,由于原先n=0,现在while n<5是成立的,于是n=n+1,n变成了1,这样就打印出了第一行结果[PRODUCER] Producing 1...。

3、produce继续执行到r=c.send(n),到这里也就是c.send(1)。send的意义是: 让generator也就是consumer继续执行,并使generator当前yield的结果变成send括号内的值也就是1,然后r=c.send(1)的意思是把生成器下次yield的结果赋值给r。执行到这里再回过头来看第一点,那么第一次运行yield的结果就从原来的空值变成1了,所以这时consumer就不会执行if not n后面的return,转而执行打印[CONSUMER] Consuming 1...语句并将 '200 OK'赋值给r了。

4、这时produce执行到下一个打印语句的时候,r就变成 '200 OK'了。

5、后面就是如此循环了,直到n=5的时候执行c.close()。

我觉得关键是要掌握generator中send的用法...

官方文档的说明:generator.send(value):

使generator继续执行并将括号内值传入generator。使得generator本次yield的结果变为括号内的值;generator.send(value)本身返回generator下次yield的值,若genertor下次不再yield结果则抛出StopIteration;若本方法是用来启动generator,则value必须为None。

consumer()中的n = yield r什么意思? yield是使改函数变成generator, 在菲波那切数列例子中,是由yield 代替 print,这出也原本是print吗?还是别的意思

教程中说: 但是Python的yield不但可以返回一个值,它还可以接收调用者发出的参数。 个人理解的意思是yield r返回r到produce,然后在produce函数中r=c.send(n),将n值作为(yield r)的返回值赋给了consumer的n,即接受了调用者produce发出的参数。

致远_易

#4 Created at ... [Delete] [Delete and Lock User]

.send()返回generator下次yield的值,为什么返回的是“200 0K”呢

我自随行

#5 Created at ... [Delete] [Delete and Lock User]
1、produce(c)开始运行,首先c.send(None)会启动generator 也就是 consumer(),第一次运行yield得到的是空值(r=''),刚好符合if not n,consumer就结束(return)了。

首先调用c.send(None)会启动generator是没错的,但是在这第一次调用generator的时候,consumer只执行到“n = yield r”就返回到produce了,请注意:“n = yield r”实际上是分两步运行的:第一步,运行表达式“yield r”,第二步,把第一步的表达式的结果赋值给n,但由于第一步是yield,所以在第一步就返回到调用者了,第二步没有执行,被挂起了,这个挂起点后面要用到。

表达式“yield r”对调用者produce的效果是返回了“r”,这样produce中的“c.send(None)”获取的返回值是空串,这个返回值在produce中被丢弃了(没有使用)。

我们注意到在这个过程当中,“n = yield r”都没有执行完,因而consumer中的“if not n: return”语句也并没有被执行。

接下来,produce中执行到了“r = c.send(1)”。这个语句的效果是让consumer从上次的挂起点(也就是“n = yield r”执行的第二步)继续执行:通过send函数把“yield r”这个表达式的结果置为传入的参数1,然后继续执行第一段中所述的第二步,这时,“n = yield r”的执行结果就是n=1。

后面就在一直重复了,直到n=5。

在这个例子中,consumer的“if not n: return”语句一直都没有被调用过,如果我们把“if not n: return”语句改为“if not n: print('return called');return”再执行,可以看到’return called‘并没有被打印出来。

这里的 r 只是一个返回值 不变的 你可以设置 r="test" print(c.send(i)) 可以发现每个都返回test n=yield r 这里也可以把r去掉,没有什么实质作用, 只是给调用方一个返回值而已.

这个普通函数就可以实现 一样的 在consumer里加上sleep 一样会锁住produce线程 感觉只是学习了个 generator.send方法


  • 1

Reply