{ "cells": [ { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": true }, "outputs": [], "source": [ "# Copyright 2014 Brett Slatkin, Pearson Education Inc.\n", "#\n", "# Licensed under the Apache License, Version 2.0 (the \"License\");\n", "# you may not use this file except in compliance with the License.\n", "# You may obtain a copy of the License at\n", "#\n", "# http://www.apache.org/licenses/LICENSE-2.0\n", "#\n", "# Unless required by applicable law or agreed to in writing, software\n", "# distributed under the License is distributed on an \"AS IS\" BASIS,\n", "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n", "# See the License for the specific language governing permissions and\n", "# limitations under the License.\n", "\n", "# Preamble to mimick book environment\n", "import logging\n", "from pprint import pprint\n", "from sys import stdout as STDOUT" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Received: First\n", "Received: Second\n" ] } ], "source": [ "# Example 1\n", "def my_coroutine():\n", " while True:\n", " received = yield\n", " print('Received:', received)\n", "\n", "it = my_coroutine()\n", "next(it) # Prime the coroutine\n", "it.send('First')\n", "it.send('Second')" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": true }, "outputs": [], "source": [ "# Example 2\n", "def minimize():\n", " current = yield\n", " while True:\n", " value = yield current\n", " current = min(value, current)" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "10\n", "4\n", "4\n", "-1\n" ] } ], "source": [ "# Example 3\n", "it = minimize()\n", "next(it) # Prime the generator\n", "print(it.send(10))\n", "print(it.send(4))\n", "print(it.send(22))\n", "print(it.send(-1))" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "collapsed": true }, "outputs": [], "source": [ "# Example 4\n", "ALIVE = '*'\n", "EMPTY = '-'" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "collapsed": true }, "outputs": [], "source": [ "# Example 5\n", "from collections import namedtuple\n", "Query = namedtuple('Query', ('y', 'x'))" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "collapsed": true }, "outputs": [], "source": [ "# Example 6\n", "def count_neighbors(y, x):\n", " n_ = yield Query(y + 1, x + 0) # North\n", " ne = yield Query(y + 1, x + 1) # Northeast\n", " # Define e_, se, s_, sw, w_, nw ...\n", " e_ = yield Query(y + 0, x + 1) # East\n", " se = yield Query(y - 1, x + 1) # Southeast\n", " s_ = yield Query(y - 1, x + 0) # South\n", " sw = yield Query(y - 1, x - 1) # Southwest\n", " w_ = yield Query(y + 0, x - 1) # West\n", " nw = yield Query(y + 1, x - 1) # Northwest\n", " neighbor_states = [n_, ne, e_, se, s_, sw, w_, nw]\n", " count = 0\n", " for state in neighbor_states:\n", " if state == ALIVE:\n", " count += 1\n", " return count" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "First yield: Query(y=11, x=5)\n", "Second yield: Query(y=11, x=6)\n", "...\n", "Count: 2\n" ] } ], "source": [ "# Example 7\n", "it = count_neighbors(10, 5)\n", "q1 = next(it) # Get the first query\n", "print('First yield: ', q1)\n", "q2 = it.send(ALIVE) # Send q1 state, get q2\n", "print('Second yield:', q2)\n", "q3 = it.send(ALIVE) # Send q2 state, get q3\n", "print('...')\n", "q4 = it.send(EMPTY)\n", "q5 = it.send(EMPTY)\n", "q6 = it.send(EMPTY)\n", "q7 = it.send(EMPTY)\n", "q8 = it.send(EMPTY)\n", "try:\n", " it.send(EMPTY) # Send q8 state, retrieve count\n", "except StopIteration as e:\n", " print('Count: ', e.value) # Value from return statement" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "collapsed": true }, "outputs": [], "source": [ "# Example 8\n", "Transition = namedtuple('Transition', ('y', 'x', 'state'))\n", "\n", "\n", "# Example 9\n", "def game_logic(state, neighbors):\n", " pass\n", "\n", "def step_cell(y, x):\n", " state = yield Query(y, x)\n", " neighbors = yield from count_neighbors(y, x)\n", " next_state = game_logic(state, neighbors)\n", " yield Transition(y, x, next_state)" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "collapsed": true }, "outputs": [], "source": [ "# Example 10\n", "def game_logic(state, neighbors):\n", " if state == ALIVE:\n", " if neighbors < 2:\n", " return EMPTY # Die: Too few\n", " elif neighbors > 3:\n", " return EMPTY # Die: Too many\n", " else:\n", " if neighbors == 3:\n", " return ALIVE # Regenerate\n", " return state" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Me: Query(y=10, x=5)\n", "Q1: Query(y=11, x=5)\n", "...\n", "Outcome: Transition(y=10, x=5, state='-')\n" ] } ], "source": [ "# Example 11\n", "it = step_cell(10, 5)\n", "q0 = next(it) # Initial location query\n", "print('Me: ', q0)\n", "q1 = it.send(ALIVE) # Send my status, get neighbor query\n", "print('Q1: ', q1)\n", "print('...')\n", "q2 = it.send(ALIVE)\n", "q3 = it.send(ALIVE)\n", "q4 = it.send(ALIVE)\n", "q5 = it.send(ALIVE)\n", "q6 = it.send(EMPTY)\n", "q7 = it.send(EMPTY)\n", "q8 = it.send(EMPTY)\n", "t1 = it.send(EMPTY) # Send for q8, get game decision\n", "print('Outcome: ', t1)" ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "collapsed": true }, "outputs": [], "source": [ "# Example 12\n", "TICK = object()\n", "\n", "def simulate(height, width):\n", " while True:\n", " for y in range(height):\n", " for x in range(width):\n", " yield from step_cell(y, x)\n", " yield TICK" ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# Example 13\n", "class Grid(object):\n", " def __init__(self, height, width):\n", " self.height = height\n", " self.width = width\n", " self.rows = []\n", " for _ in range(self.height):\n", " self.rows.append([EMPTY] * self.width)\n", "\n", " def __str__(self):\n", " output = ''\n", " for row in self.rows:\n", " for cell in row:\n", " output += cell\n", " output += '\\n'\n", " return output\n", "\n", "# Example 14\n", " def query(self, y, x):\n", " return self.rows[y % self.height][x % self.width]\n", "\n", " def assign(self, y, x, state):\n", " self.rows[y % self.height][x % self.width] = state" ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "collapsed": true }, "outputs": [], "source": [ "# Example 15\n", "def live_a_generation(grid, sim):\n", " progeny = Grid(grid.height, grid.width)\n", " item = next(sim)\n", " while item is not TICK:\n", " if isinstance(item, Query):\n", " state = grid.query(item.y, item.x)\n", " item = sim.send(state)\n", " else: # Must be a Transition\n", " progeny.assign(item.y, item.x, item.state)\n", " item = next(sim)\n", " return progeny" ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "---*-----\n", "----*----\n", "--***----\n", "---------\n", "---------\n", "\n" ] } ], "source": [ "# Example 16\n", "grid = Grid(5, 9)\n", "grid.assign(0, 3, ALIVE)\n", "grid.assign(1, 4, ALIVE)\n", "grid.assign(2, 2, ALIVE)\n", "grid.assign(2, 3, ALIVE)\n", "grid.assign(2, 4, ALIVE)\n", "print(grid)" ] }, { "cell_type": "code", "execution_count": 16, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " 0 | 1 | 2 | 3 | 4 \n", "---*----- | --------- | --------- | --------- | ---------\n", "----*---- | --*-*---- | ----*---- | ---*----- | ----*----\n", "--***---- | ---**---- | --*-*---- | ----**--- | -----*---\n", "--------- | ---*----- | ---**---- | ---**---- | ---***---\n", "--------- | --------- | --------- | --------- | ---------\n" ] } ], "source": [ "# Example 17\n", "class ColumnPrinter(object):\n", " def __init__(self):\n", " self.columns = []\n", "\n", " def append(self, data):\n", " self.columns.append(data)\n", "\n", " def __str__(self):\n", " row_count = 1\n", " for data in self.columns:\n", " row_count = max(row_count, len(data.splitlines()) + 1)\n", " rows = [''] * row_count\n", " for j in range(row_count):\n", " for i, data in enumerate(self.columns):\n", " line = data.splitlines()[max(0, j - 1)]\n", " if j == 0:\n", " padding = ' ' * (len(line) // 2)\n", " rows[j] += padding + str(i) + padding\n", " else:\n", " rows[j] += line\n", " if (i + 1) < len(self.columns):\n", " rows[j] += ' | '\n", " return '\\n'.join(rows)\n", "\n", "columns = ColumnPrinter()\n", "sim = simulate(grid.height, grid.width)\n", "for i in range(5):\n", " columns.append(str(grid))\n", " grid = live_a_generation(grid, sim)\n", "\n", "print(columns)" ] }, { "cell_type": "code", "execution_count": 17, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "['A', 1, 2, 'B']\n" ] } ], "source": [ "# Example 18\n", "def delegated():\n", " yield 1\n", " yield 2\n", "\n", "def composed():\n", " yield 'A'\n", " for value in delegated(): # yield from in Python 3\n", " yield value\n", " yield 'B'\n", "\n", "print(list(composed()))\n" ] }, { "cell_type": "code", "execution_count": 18, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[1, 8]\n" ] } ], "source": [ "# Example 19\n", "class MyReturn(Exception):\n", " def __init__(self, value):\n", " self.value = value\n", "\n", "def delegated():\n", " yield 1\n", " raise MyReturn(2) # return 2 in Python 3\n", " yield 'Not reached'\n", "\n", "def composed():\n", " try:\n", " for value in delegated():\n", " yield value\n", " except MyReturn as e:\n", " output = e.value\n", " yield output * 4\n", "\n", "print(list(composed()))\n" ] }, { "cell_type": "code", "execution_count": 19, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " 0 | 1 | 2 | 3 | 4 \n", "----- | ----- | ----- | ----- | -----\n", "-*--- | --*-- | --**- | --*-- | -----\n", "--**- | --**- | -*--- | -*--- | -**--\n", "---*- | --**- | --**- | --*-- | -----\n", "----- | ----- | ----- | ----- | -----\n" ] } ], "source": [ "# Example 20\n", "# This is for the introductory diagram\n", "grid = Grid(5, 5)\n", "grid.assign(1, 1, ALIVE)\n", "grid.assign(2, 2, ALIVE)\n", "grid.assign(2, 3, ALIVE)\n", "grid.assign(3, 3, ALIVE)\n", "\n", "columns = ColumnPrinter()\n", "sim = simulate(grid.height, grid.width)\n", "for i in range(5):\n", " columns.append(str(grid))\n", " grid = live_a_generation(grid, sim)\n", "\n", "print(columns)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.5.1" } }, "nbformat": 4, "nbformat_minor": 0 }