Last active
August 29, 2015 14:09
-
-
Save pgk/54043d787154740f243c to your computer and use it in GitHub Desktop.
Generator Examples ipython notebook
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"metadata": { | |
"name": "" | |
}, | |
"nbformat": 3, | |
"nbformat_minor": 0, | |
"worksheets": [ | |
{ | |
"cells": [ | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"# Python Generators\n", | |
"\n", | |
"## What they do\n", | |
"\n", | |
"* They allow a function to behave as an `Iterator` object.\n", | |
"* They can be used to emulate state and concurrency (more on that later)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"\n", | |
"def count(a):\n", | |
" \"\"\"counts elements of an iterable\"\"\"\n", | |
" c = 0\n", | |
" for i in a:\n", | |
" c += 1\n", | |
" return c\n", | |
"\n", | |
"# an array\n", | |
"a = range(10)\n", | |
"\n", | |
"print(count(a))\n", | |
"\n", | |
"# but what happens as it grows?\n", | |
"\n", | |
"# a = range(2**16)\n", | |
"# a = range(2**32) ??? memory swapping\n", | |
"# memory is not Infinite\n", | |
"# range creates the whole array in one go. \n", | |
"\n", | |
"# consider this\n", | |
"\n", | |
"# Problem: Memory is finite. I want to pretend it's infinite\n", | |
"# Solution: create an iterator\n", | |
"# iterator is any object that implements __iter__ \n", | |
"# and returns an iterable object that implements __next__ or next in py3)\n", | |
"\n", | |
"\n", | |
"class crange(object):\n", | |
" \"\"\"range replacement iterator\"\"\"\n", | |
" def __init__(self, start, end=None, step=1):\n", | |
" if not end:\n", | |
" end = start\n", | |
" start = 0\n", | |
" assert start <= end\n", | |
" self.start = start\n", | |
" self.end = end\n", | |
" self.step = step\n", | |
"\n", | |
" def next(self):\n", | |
" if self.start >= self.end:\n", | |
" raise StopIteration()\n", | |
"\n", | |
" res = self.start\n", | |
" self.start += self.step\n", | |
" return res\n", | |
"\n", | |
" __next__ = next\n", | |
"\n", | |
" def __iter__(self):\n", | |
" return self\n", | |
" \n", | |
"for i in crange(10):\n", | |
" print(i)\n", | |
"\n", | |
"\n", | |
"# generator expression:\n", | |
"a = (i for i in xrange(10))\n", | |
"\n", | |
"# but c'mon a whole class for a friggin iterator?\n", | |
"# Solution 2: Use a Generator function (a function that yields)\n", | |
"def irange(start, end=None, step=1):\n", | |
" \"\"\"go from `start` to `end` by `step`\"\"\"\n", | |
" if not end:\n", | |
" start, end = 0, start\n", | |
"\n", | |
" while start < end:\n", | |
" yield start\n", | |
" start += step\n", | |
"\n", | |
"\n", | |
"for i in irange(0,10):\n", | |
" print(i)\n", | |
"\n", | |
"\n", | |
"\n", | |
"# force generator to run fully by using it in a constructor\n", | |
"a = list(irange(0, 10))\n", | |
"print(a)\n", | |
"\n", | |
"\n", | |
"def mdict():\n", | |
" yield 'foo', 1\n", | |
" yield 'bar', 2\n", | |
"\n", | |
"try:\n", | |
" gen = mdict()\n", | |
" print gen.next()\n", | |
" print gen.next()\n", | |
" print gen.next()\n", | |
"except StopIteration, se:\n", | |
" print('mdict finished thus StopIteration was raised')\n", | |
"\n", | |
" \n", | |
"\n" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"stream": "stdout", | |
"text": [ | |
"10\n", | |
"0\n", | |
"1\n", | |
"2\n", | |
"3\n", | |
"4\n", | |
"5\n", | |
"6\n", | |
"7\n", | |
"8\n", | |
"9\n", | |
"0\n", | |
"1\n", | |
"2\n", | |
"3\n", | |
"4\n", | |
"5\n", | |
"6\n", | |
"7\n", | |
"8\n", | |
"9\n", | |
"[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]\n", | |
"('foo', 1)\n", | |
"('bar', 2)\n", | |
"mdict finished thus StopIteration was raised\n" | |
] | |
} | |
], | |
"prompt_number": 4 | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"# Generators and concurrency\n", | |
"\n", | |
"### Let's revisit `yield` semantics\n", | |
"\n", | |
"* Can be suspended by the consumer, saving the state with it\n", | |
"* It is resumed by the consumer\n", | |
"* It can receive values from the consumer and return values to it\n", | |
"* It can raise exceptions\n", | |
"\n", | |
"### Let's revisit Coroutines\n", | |
"\n", | |
"* Can be suspended by another coroutine or itself, saving the state with it\n", | |
"* It is resumed by another coroutine\n", | |
"* It can receive values from another coroutine\n", | |
"\n", | |
"\n" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"print \"Hello\"" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"stream": "stdout", | |
"text": [ | |
"Hello\n" | |
] | |
} | |
], | |
"prompt_number": 18 | |
} | |
], | |
"metadata": {} | |
} | |
] | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
pip install pyzmq | |
pip install ipython |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment