当生成器函数需要接收一个可变的动态的参数来改变函数输出结果时,我们可以考虑使用send方法。
迭代器有一个send方法,可以将动态的数据注入到生成器函数中。
# 定义生成器函数
def my_generator():received = yield 1print(f'received = {received}')# 调用生成器获取迭代器对象
it = iter(my_generator())
# 获取迭代器值
output = next(it)
print(f'output = {output}')
try:# 因为生成器只输出了一个值,再次获取值时为Nonenext(it)
except StopIteration:pass
运行上面的代码查看结果
output = 1
received = None
# 定义生成器函数
def my_generator():received = yield 1print(f'received = {received}')# 调用生成器获取迭代器对象
it = iter(my_generator())
# 通过send方法获取生成器的值
output = it.send(None)
print(f'output = {output}')try:# send方法向生成器注入数据,并获取它返回的数据it.send('hello')
except StopIteration:pass
运行上面的代码查看结果,生成器输出了shend方法注入的hello参数。
output = 1
received = hello
在使用send方法获取生成器值的时候,传入的参数会成为生成器上一条yield表达式的值,生成器拿到这个值后会运行下一条yield表达式哪里。因此刚开始运行生成器的时候,他是从头执行的,这个时候生成器还没有产出数据,所以首次调用send方法时,只能传入None,要是传入其他值,就会抛出异常。
def wave_send(steps):step_size = 2 * math.pi / steps# 接收send方法注入的数据amplitude = yieldfor step in range(steps):radians = step * step_sizefraction = math.sin(radians)output = amplitude * fraction# yield右侧是生成器输出的值,左侧是将send参数赋值给amplitudeamplitude = yield output# 接收wave_send生成器的输出值
def transmit_send(output):if output is None:print(f'Output is None')else:print(f'Output: {output:>5.1f}')# 调用生成器
def run_send(it):amplitudes = [None, 2, 5, 7, 8, 5, 6, 4, 3, 3]for amplitude in amplitudes:# 通过send方法给生成器注入数据,send返回值是生成器输出的值。output = it.send(amplitude)transmit_send(output)run_send(wave_send(12))
运行上面代码,amplitude值动态变化使生成器的结果随之改变。
Output is None
Output: 0.0
Output: 2.5
Output: 6.1
Output: 8.0
Output: 4.3
Output: 3.0
Output: 0.0
Output: -1.5
Output: -2.6
如果我们需要调用多个生成器时候,是不建议使用send方法,它有两个弊端。
def complex_wave_moudulating():# 通过yield from可以将多个生成器连接使用yield from wave_send(3)yield from wave_send(4)yield from wave_send(5)run_send(complex_wave_moudulating())
运行上面的代码,输出结果显示输出了三个None,并且最后一个生成器值丢失。
Output is None
Output: 0.0
Output: 4.3
Output: -6.1
Output is None
Output: 0.0
Output: 6.0
Output: 0.0
Output: -3.0
Output is None
# amplitude_it是一个迭代器
def wave_cascading(amplitude_it, steps):step_size = 2 * math.pi / stepsfor step in range(steps):radians = step * step_sizefraction = math.sin(radians)# 从迭代器中获取一个值amplitude = next(amplitude_it)output = amplitude * fractionyield outputdef complex_wave_moudulating(amplitude_it):yield from wave_cascading(amplitude_it, 3)yield from wave_cascading(amplitude_it, 4)yield from wave_cascading(amplitude_it, 5)def transmit_moudul(output):if output is None:print(f'Output is None')else:print(f'run_cascading: {output:>5.1f}')
def run_cascading():amplitudes = [2, 5, 7, 8, 5, 6, 4, 3, 3]# 使用iter返回一个迭代器对象it = complex_wave_moudulating(iter(amplitudes))for amplitude in amplitudes:output = next(it)transmit_moudul(output)
run_cascading()
运行上面的代码查看结果
run_cascading: 0.0
run_cascading: 4.3
run_cascading: -6.1
run_cascading: 0.0
run_cascading: 5.0
run_cascading: 0.0
run_cascading: -4.0
run_cascading: 0.0
run_cascading: 2.9
下一篇:平面上最接近点对(分治法)