尝试将收益理解为一种表达 [英] Attempting to understand yield as an expression

查看:62
本文介绍了尝试将收益理解为一种表达的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用生成器和生成器表达式,但我不确定是否完全了解它们的工作方式(一些参考资料):

I'm playing around with generators and generator expressions and I'm not completely sure that I understand how they work (some reference material):

>>> a = (x for x in range(10))
>>> next(a)
0
>>> next(a)
1
>>> a.send(-1)
2
>>> next(a)
3

所以看来generator.send被忽略了.这是有道理的(我想),因为没有显式的yield表达式可以捕获发送的信息...

So it looks like generator.send was ignored. That makes sense (I guess) because there is no explicit yield expression to catch the sent information ...

但是,

>>> a = ((yield x) for x in range(10))
>>> next(a)
0
>>> print next(a)
None
>>> print next(a)
1
>>> print next(a)
None
>>> a.send(-1)  #this send is ignored, Why? ... there's a yield to catch it...
2
>>> print next(a)
None
>>> print next(a)
3
>>> a.send(-1)  #this send isn't ignored
-1

我知道这很遥远,而且(目前)我无法想到一个用例(所以不要问;)

I understand this is pretty far out there, and I (currently) can't think of a use-case for this (so don't ask;)

我主要是为了尝试弄清楚这些各种生成器方法如何工作(以及生成器表达式通常如何工作).为什么我的第二个示例在产生有意义的值和None之间交替显示?另外,谁能解释为什么我的generator.send之一被忽略而另一个却未被忽略?

I'm mostly just exploring to try to figure out how these various generator methods work (and how generator expressions work in general). Why does my second example alternate between yielding a sensible value and None? Also, Can anyone explain why one of my generator.send's was ignored while the other wasn't?

推荐答案

此处的困惑在于生成器表达式正在执行隐藏的yield.这是函数形式:

The confusion here is that the generator expression is doing a hidden yield. Here it is in function form:

def foo():
    for x in range(10):
        yield (yield x)

执行.send()时,将执行内部yield x,这将产生x.然后,表达式的结果为.send的值,下一个yield产生该值.这是更清晰的形式:

When you do a .send(), what happens is the inner yield x gets executed, which yields x. Then the expression evaluates to the value of the .send, and the next yield yields that. Here it is in clearer form:

def foo():
    for x in range(10):
        sent_value = (yield x)
        yield sent_value

因此,输出是非常可预测的:

Thus the output is very predictable:

>>> a = foo()
#start it off
>>> a.next() 
0
#execution has now paused at "sent_value = ?"
#now we fill in the "?". whatever we send here will be immediately yielded.
>>> a.send("yieldnow") 
'yieldnow'
#execution is now paused at the 'yield sent_value' expression
#as this is not assigned to anything, whatever is sent now will be lost
>>> a.send("this is lost") 
1
#now we're back where we were at the 'yieldnow' point of the code
>>> a.send("yieldnow") 
'yieldnow'
#etc, the loop continues
>>> a.send("this is lost")
2
>>> a.send("yieldnow")
'yieldnow'
>>> a.send("this is lost")
3
>>> a.send("yieldnow")
'yieldnow'

用法示例.到目前为止,我见过的最酷的一个是Twisted的inlineCallbacks函数. 请参阅此处,以获取有关其解释的文章.它的不足之处在于它使您可以让函数在线程中运行,并且一旦函数完成,twisted会将函数的结果发送回代码中.因此,您可以以非常线性和直观的方式编写高度依赖线程的代码,而不必到处编写大量的小功能.

Example usage. By far the coolest one I've seen so far is twisted's inlineCallbacks function. See here for an article explaining it. The nub of it is it lets you yield functions to be run in threads, and once the functions are done, twisted sends the result of the function back into your code. Thus you can write code that heavily relies on threads in a very linear and intuitive manner, instead of having to write tons of little functions all over the place.

请参阅 PEP 342 ,详细了解具有.send处理潜在的用例(我提供的扭曲示例是该更改提供的异步I/O的一个示例).

See the PEP 342 for more info on the rationale of having .send work with potential use cases (the twisted example I provided is an example of the boon to asynchronous I/O this change offered).

这篇关于尝试将收益理解为一种表达的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆