关于 yield 返回值的问题请教

2017-11-08 18:57:06 +08:00
 saximi
def gen(): 
        for i in range(1): 
                print('i=',i) 
                X = yield i 
                print('X=',X) 

G = gen()  
print('next(G)=',next(G))  
print('next(G)=',next(G))   


上面代码输出如下,可见如果等号的右边如果是 yield 语句,则等号左边的变量值默认是 None,除非用 send 语句对它赋值: 
i= 0 
next(G)= 0 
X= None 
Traceback (most recent call last): 
  File "c:\Users\rubin\AppData\Roaming\Code\User\rb\t.py", line 9, in  
    print('next(G)=',next(G)) 
StopIteration 


但是对于下面的例子来说,即使没有用 send 语句,yield 返回的值也能赋值给等号左边的变量 reader 和 writer。 
import asyncio 
@asyncio.coroutine 
def wget(host): 
    print('wget %s...' % host) 
    connect = asyncio.open_connection(host, 80) 
    reader, writer = yield from connect     #yield 返回的值也能赋值给等号左边的变量 
    header = 'GET / HTTP/1.0\r\nHost: %s\r\n\r\n' % host 
    print('reader=%s write=%s' % (reader,writer))  
    writer.write(header.encode('utf-8')) 
    yield from writer.drain() 
    writer.close() 

loop = asyncio.get_event_loop() 
tasks = [wget(host) for host in ['www.sohu.com']] 
loop.run_until_complete(asyncio.wait(tasks)) 
loop.close() 

上面代码输出如下: 
wget  www.sohu.com. .. 
reader=<StreamReader t=<_SelectorSocketTransport fd=592 read=polling write=<idle, bufsize=0>>> write=<StreamWriter transport=<_SelectorSocketTransport fd=592 read=polling write=<idle, bufsize=0>> reader=<StreamReader t=<_SelectorSocketTransport fd=592 read=polling write=<idle, bufsize=0>>>>

为何等号左边的变量 reader 和 writer 不是 None ?请问这是什么原理呢?谢谢!

3569 次点击
所在节点    Python
4 条回复
smallzhan
2017-11-08 21:15:33 +08:00
一个是 yield,一个是 yield from。
yield 和 yield from 是不同的,你可以看看 fluent python,coroutine 那章讲这个的。顺便还有 asyncio 那章。
xlui
2017-11-08 22:27:38 +08:00
第二个例子中的 connect 变量是一个 generator,yield from 会自动对它进行预激,也就是调用 next(connect),并且自动迭代 connect 生成值,然后返回结果。具体可以去看 流畅的 Python,这本书真的值得买回来。
guyskk0x0
2017-11-08 22:50:55 +08:00
@asyncio.coroutine 会自动帮你调用 send,过程比较 复杂,可以到 YouTube 上搜 async 或 coroutine,有很多大牛的演讲视频。
wzwwzw
2017-11-09 15:38:32 +08:00
看下流畅的 Python 16 章节 。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/404705

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX