您的位置:首页 > 编程语言 > Python开发

python yield 实例理解要点

2015-08-19 23:45 676 查看
结合下面代码为例理解:

1、函数对象包含yield语句后,yield_in_loop变成了generatorfunction,成了generatorType对象的构造器

2、yield_in_loop() 每次调用产生一个iterable可迭代的generator,对象实例互不影响

3、每次generator的实例执行next()才开始执行yield语句生成迭代结果(yield后可以为逗号分开的多个对象)并在该语句后立即中断待命,(如有下个yield语句可执行,下次执行则从紧随yield的下一个语句执行至下下个yield语句中断......)

4、send(arg)给generator的arg替换当前yield的迭代结果【首次迭代send(None)=next(),首次参数必须为None,因为还没有开始执行的yield表达式,就没有地方可以send值】

5、send(arg)的返回值就就是传递给下一个yield表达式的值,也即send(arg)的返回值来自下一个yield表达式的值,而不是来自接受send(arg)传递值的yield表达式,“回音壁”!

# -*- coding: utf-8 -*-
'''
Created on 2015年8月17日

@author: laughlast
'''
from inspect import isgeneratorfunction
from collections import Iterable
import unittest
import types

def yield_in_loop():
sendlist = []
for i in range(1, 4):
# yield可产生多个值
y = yield i, sendlist
sendlist.append(y)
print '#', i, y, sendlist
class Test(unittest.TestCase):
def test1_next_yield(self):
'''test1_next_yield'''
y1 = yield_in_loop()
self.assertIsInstance(yield_in_loop(), types.GeneratorType, \
'yield_in_loop():是生成器类型')
self.assertIsInstance(yield_in_loop(), Iterable, \
'yield_in_loop():是迭代器类型')
self.assertTrue(isgeneratorfunction(yield_in_loop), \
'yield_in_loop:是生成器函数类型,不是生成器')
self.assertFalse(isinstance(yield_in_loop, (Iterable, types.GeneratorType)), \
'yield_in_loop:不是生成器、迭代类型')
self.assertEqual(y1.next()[0], 1, '当为 1')
y = y1.next()
self.assertEqual(y[0], 2, '当为 2')
self.assertIsInstance(y, types.TupleType, \
'yield语句后面传回多个参数,生成的值为tuple系列类型')
# 迭代器特性,y为元组Tuple解包
i, sendlist = y1.next()
self.assertEqual(i, 3, '当为 3')
self.assertTrue(sendlist == [None, None], 'next()无值传递')
with self.assertRaises(StopIteration):
# 'StopIteration:“迭”停'
y1.next()
self.fail('来错地方了')
def test2_send_yield(self):
'''test2_send_yield'''
y1 = yield_in_loop()
with self.assertRaises(TypeError):
self.assertEqual(y1.send('Not None'), 1, \
'TypeError:首次只能send(None)')
self.assertEqual(y1.send(None)[0], 1, '当为 1')
self.assertEqual(y1.send(88)[0], 2, '当为 2')
# i为被替换的yield本身正常迭代结果,sendlist保存的是send(99)替换后的yield迭代结果
i, sendlist = y1.send(99)
self.assertEqual(i, 3, '当为 3')
self.assertTrue(sendlist == [88, 99], '当为[88, 99]')
with self.assertRaises(StopIteration):
# 'StopIteration:“迭”停'
i, sendlist = y1.send(100)
self.fail('来错地方了')
# send(100):100替换掉当前yield的迭代值3(上面处理generator产生的异常StopIteration)
self.assertTrue(sendlist == [88, 99, 100], '当为[88, 99,100]')
if __name__ == "__main__":
unittest.main()

#测试输出
# 1 None [None].
# 2 None [None, None]
# 3 None [None, None, None]
# 1 88 [88]
# 2 99 [88, 99]
# 3 100 [88, 99, 100]
.
----------------------------------------------------------------------
Ran 2 tests in 0.000s

OK
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: