#!/usr/bin/env PYTHONHASHSEED=1234 python3 # Copyright 2014-2019 Brett Slatkin, Pearson Education Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Reproduce book environment import random random.seed(1234) import logging from pprint import pprint from sys import stdout as STDOUT # Write all output to a temporary directory import atexit import gc import io import os import tempfile TEST_DIR = tempfile.TemporaryDirectory() atexit.register(TEST_DIR.cleanup) # Make sure Windows processes exit cleanly OLD_CWD = os.getcwd() atexit.register(lambda: os.chdir(OLD_CWD)) os.chdir(TEST_DIR.name) def close_open_files(): everything = gc.get_objects() for obj in everything: if isinstance(obj, io.IOBase): obj.close() atexit.register(close_open_files) # Example 1 import math def wave(amplitude, steps): step_size = 2 * math.pi / steps for step in range(steps): radians = step * step_size fraction = math.sin(radians) output = amplitude * fraction yield output # Example 2 def transmit(output): if output is None: print(f'Output is None') else: print(f'Output: {output:>5.1f}') def run(it): for output in it: transmit(output) run(wave(3.0, 8)) # Example 3 def my_generator(): received = yield 1 print(f'received = {received}') it = my_generator() output = next(it) # Get first generator output print(f'output = {output}') try: next(it) # Run generator until it exits except StopIteration: pass else: assert False # Example 4 it = my_generator() output = it.send(None) # Get first generator output print(f'output = {output}') try: it.send('hello!') # Send value into the generator except StopIteration: pass else: assert False # Example 5 def wave_modulating(steps): step_size = 2 * math.pi / steps amplitude = yield # Receive initial amplitude for step in range(steps): radians = step * step_size fraction = math.sin(radians) output = amplitude * fraction amplitude = yield output # Receive next amplitude # Example 6 def run_modulating(it): amplitudes = [ None, 7, 7, 7, 2, 2, 2, 2, 10, 10, 10, 10, 10] for amplitude in amplitudes: output = it.send(amplitude) transmit(output) run_modulating(wave_modulating(12)) # Example 7 def complex_wave(): yield from wave(7.0, 3) yield from wave(2.0, 4) yield from wave(10.0, 5) run(complex_wave()) # Example 8 def complex_wave_modulating(): yield from wave_modulating(3) yield from wave_modulating(4) yield from wave_modulating(5) run_modulating(complex_wave_modulating()) # Example 9 def wave_cascading(amplitude_it, steps): step_size = 2 * math.pi / steps for step in range(steps): radians = step * step_size fraction = math.sin(radians) amplitude = next(amplitude_it) # Get next input output = amplitude * fraction yield output # Example 10 def complex_wave_cascading(amplitude_it): yield from wave_cascading(amplitude_it, 3) yield from wave_cascading(amplitude_it, 4) yield from wave_cascading(amplitude_it, 5) # Example 11 def run_cascading(): amplitudes = [7, 7, 7, 2, 2, 2, 2, 10, 10, 10, 10, 10] it = complex_wave_cascading(iter(amplitudes)) for amplitude in amplitudes: output = next(it) transmit(output) run_cascading()