Last active
December 12, 2015 03:28
-
-
Save sparkiegeek/4706674 to your computer and use it in GitHub Desktop.
Advanced Python Tutorial from PyGround, Timisoara - Feb 2013
This file contains hidden or 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": "Advanced Python Programming" | |
| }, | |
| "nbformat": 3, | |
| "nbformat_minor": 0, | |
| "worksheets": [ | |
| { | |
| "cells": [ | |
| { | |
| "cell_type": "heading", | |
| "level": 2, | |
| "metadata": {}, | |
| "source": [ | |
| "Who am I?" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": {}, | |
| "source": [ | |
| "Adam Collard [@acollard](http://twitter.com/acollard)\n", | |
| "\n", | |
| "Sofware Architect at Cmed Technology" | |
| ] | |
| }, | |
| { | |
| "cell_type": "heading", | |
| "level": 2, | |
| "metadata": {}, | |
| "source": [ | |
| "Topics" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": {}, | |
| "source": [ | |
| "* Functional programming\n", | |
| "* Iterators and generators" | |
| ] | |
| }, | |
| { | |
| "cell_type": "heading", | |
| "level": 2, | |
| "metadata": {}, | |
| "source": [ | |
| "What is Functional Programming?" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "collapsed": false, | |
| "input": [ | |
| "def one():\n", | |
| " \"\"\"It's 42/42\"\"\"\n", | |
| " return 1\n", | |
| "\n", | |
| "def incrementer(function):\n", | |
| " \"\"\"Adds one to the result of the given function\"\"\"\n", | |
| " return function() + 1" | |
| ], | |
| "language": "python", | |
| "metadata": {}, | |
| "outputs": [], | |
| "prompt_number": 2 | |
| }, | |
| { | |
| "cell_type": "code", | |
| "collapsed": true, | |
| "input": [ | |
| "incrementer(one)" | |
| ], | |
| "language": "python", | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "output_type": "pyout", | |
| "prompt_number": 3, | |
| "text": [ | |
| "2" | |
| ] | |
| } | |
| ], | |
| "prompt_number": 3 | |
| }, | |
| { | |
| "cell_type": "code", | |
| "collapsed": false, | |
| "input": [ | |
| "def multiplier(function, times=5):\n", | |
| " \"\"\"Multiplies result of given function by <times> times, default 5\"\"\"\n", | |
| " return function() * times" | |
| ], | |
| "language": "python", | |
| "metadata": {}, | |
| "outputs": [], | |
| "prompt_number": 4 | |
| }, | |
| { | |
| "cell_type": "code", | |
| "collapsed": true, | |
| "input": [ | |
| "multiplier(one)" | |
| ], | |
| "language": "python", | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "output_type": "pyout", | |
| "prompt_number": 5, | |
| "text": [ | |
| "5" | |
| ] | |
| } | |
| ], | |
| "prompt_number": 5 | |
| }, | |
| { | |
| "cell_type": "code", | |
| "collapsed": true, | |
| "input": [ | |
| "map(int, [\"1\", \"0\", \"2\", \"25\"])" | |
| ], | |
| "language": "python", | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "output_type": "pyout", | |
| "prompt_number": 6, | |
| "text": [ | |
| "[1, 0, 2, 25]" | |
| ] | |
| } | |
| ], | |
| "prompt_number": 6 | |
| }, | |
| { | |
| "cell_type": "code", | |
| "collapsed": true, | |
| "input": [ | |
| "filter(lambda x: x % 2 == 0, range(5))" | |
| ], | |
| "language": "python", | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "output_type": "pyout", | |
| "prompt_number": 7, | |
| "text": [ | |
| "[0, 2, 4]" | |
| ] | |
| } | |
| ], | |
| "prompt_number": 7 | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": {}, | |
| "source": [ | |
| "Functions are first class objects in Python!\n", | |
| "\n", | |
| " - Can be passed to other functions\n", | |
| " - Can be stored in lists, dictionaries, ...\n", | |
| " - Have attributes" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "collapsed": false, | |
| "input": [ | |
| "doers = [multiplier, incrementer]\n", | |
| "\n", | |
| "for function in doers:\n", | |
| " print function.__name__, \"=\", function(one)" | |
| ], | |
| "language": "python", | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "output_type": "stream", | |
| "stream": "stdout", | |
| "text": [ | |
| "multiplier = 5\n", | |
| "incrementer = 2\n" | |
| ] | |
| } | |
| ], | |
| "prompt_number": 8 | |
| }, | |
| { | |
| "cell_type": "code", | |
| "collapsed": true, | |
| "input": [ | |
| "multiplier.__doc__" | |
| ], | |
| "language": "python", | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "output_type": "pyout", | |
| "prompt_number": 9, | |
| "text": [ | |
| "'Multiplies result of given function by <times> times, default 5'" | |
| ] | |
| } | |
| ], | |
| "prompt_number": 9 | |
| }, | |
| { | |
| "cell_type": "heading", | |
| "level": 2, | |
| "metadata": {}, | |
| "source": [ | |
| "Why should I care?" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": {}, | |
| "source": [ | |
| "Functional programming offers several benefits:\n", | |
| "\n", | |
| "* Clean design\n", | |
| "* Composable\n", | |
| "* Simple\n", | |
| "* Easily testable\n", | |
| "* Easily scalable" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "collapsed": false, | |
| "input": [ | |
| "%load_ext ipython_nose" | |
| ], | |
| "language": "python", | |
| "metadata": {}, | |
| "outputs": [], | |
| "prompt_number": 2 | |
| }, | |
| { | |
| "cell_type": "code", | |
| "collapsed": false, | |
| "input": [ | |
| "def only_evens(a_list):\n", | |
| " return [x for x in a_list if x % 2 == 0]\n", | |
| "\n", | |
| "def test_empty_list():\n", | |
| " \"\"\"Test empty list is empty\"\"\"\n", | |
| " assert only_evens([]) == []\n", | |
| " \n", | |
| "def test_single_even_element():\n", | |
| " \"\"\"Test with single element\"\"\"\n", | |
| " assert only_evens([2]) == [2]\n", | |
| " \n", | |
| "def test_odds_filtered():\n", | |
| " \"\"\"Test we odd numbers not included\"\"\"\n", | |
| " assert only_evens([1, 2, 3, 4]) == [2, 4]\n", | |
| " \n", | |
| "def test_zero_included():\n", | |
| " \"\"\"Test 0 is counted as even\"\"\"\n", | |
| " assert only_evens([0, 1, 2, 3]) == [0, 2]\n", | |
| "\n", | |
| "#import unittest\n", | |
| "#class OnlyEvensTest(unittest.TestCase):\n", | |
| "# \n", | |
| "# def test_foo(self):\n", | |
| "# self.assertFalse()\n", | |
| "\n" | |
| ], | |
| "language": "python", | |
| "metadata": {}, | |
| "outputs": [], | |
| "prompt_number": 4 | |
| }, | |
| { | |
| "cell_type": "code", | |
| "collapsed": true, | |
| "input": [ | |
| "# This is IPython magic..\n", | |
| "%nose" | |
| ], | |
| "language": "python", | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "html": [ | |
| "<div id=\"ipython_nose_aefb48046ca54c7b931b96e1d9511d87\"></div>" | |
| ], | |
| "output_type": "display_data" | |
| }, | |
| { | |
| "javascript": [ | |
| "document.ipython_nose_aefb48046ca54c7b931b96e1d9511d87 = $(\"#ipython_nose_aefb48046ca54c7b931b96e1d9511d87\");" | |
| ], | |
| "output_type": "display_data" | |
| }, | |
| { | |
| "javascript": [ | |
| "document.ipython_nose_aefb48046ca54c7b931b96e1d9511d87.append($(\"<span>.</span>\"));" | |
| ], | |
| "output_type": "display_data" | |
| }, | |
| { | |
| "javascript": [ | |
| "document.ipython_nose_aefb48046ca54c7b931b96e1d9511d87.append($(\"<span>.</span>\"));" | |
| ], | |
| "output_type": "display_data" | |
| }, | |
| { | |
| "javascript": [ | |
| "document.ipython_nose_aefb48046ca54c7b931b96e1d9511d87.append($(\"<span>.</span>\"));" | |
| ], | |
| "output_type": "display_data" | |
| }, | |
| { | |
| "javascript": [ | |
| "document.ipython_nose_aefb48046ca54c7b931b96e1d9511d87.append($(\"<span>.</span>\"));" | |
| ], | |
| "output_type": "display_data" | |
| }, | |
| { | |
| "javascript": [ | |
| "delete document.ipython_nose_aefb48046ca54c7b931b96e1d9511d87;" | |
| ], | |
| "output_type": "display_data" | |
| }, | |
| { | |
| "html": [ | |
| " <style type=\"text/css\">\n", | |
| " span.nosefailedfunc {\n", | |
| " font-family: monospace;\n", | |
| " font-weight: bold;\n", | |
| " }\n", | |
| " div.noseresults {\n", | |
| " width: 100%;\n", | |
| " }\n", | |
| " div.nosebar {\n", | |
| " float: left;\n", | |
| " padding: 1ex 0px 1ex 0px;\n", | |
| " }\n", | |
| " div.nosebar.fail {\n", | |
| " background: #ff3019; /* Old browsers */\n", | |
| " /* FF3.6+ */\n", | |
| " background: -moz-linear-gradient(top, #ff3019 0%, #cf0404 100%);\n", | |
| " /* Chrome,Safari4+ */\n", | |
| " background: -webkit-gradient(linear, left top, left bottom,\n", | |
| " color-stop(0%,#ff3019),\n", | |
| " color-stop(100%,#cf0404));\n", | |
| " /* Chrome10+,Safari5.1+ */\n", | |
| " background: -webkit-linear-gradient(top, #ff3019 0%,#cf0404 100%);\n", | |
| " /* Opera 11.10+ */\n", | |
| " background: -o-linear-gradient(top, #ff3019 0%,#cf0404 100%);\n", | |
| " /* IE10+ */\n", | |
| " background: -ms-linear-gradient(top, #ff3019 0%,#cf0404 100%);\n", | |
| " /* W3C */\n", | |
| " background: linear-gradient(to bottom, #ff3019 0%,#cf0404 100%);\n", | |
| " }\n", | |
| " div.nosebar.pass {\n", | |
| " background: #52b152;\n", | |
| " background: -moz-linear-gradient(top, #52b152 1%, #008a00 100%);\n", | |
| " background: -webkit-gradient(linear, left top, left bottom,\n", | |
| " color-stop(1%,#52b152),\n", | |
| " color-stop(100%,#008a00));\n", | |
| " background: -webkit-linear-gradient(top, #52b152 1%,#008a00 100%);\n", | |
| " background: -o-linear-gradient(top, #52b152 1%,#008a00 100%);\n", | |
| " background: -ms-linear-gradient(top, #52b152 1%,#008a00 100%);\n", | |
| " background: linear-gradient(to bottom, #52b152 1%,#008a00 100%);\n", | |
| " }\n", | |
| " div.nosebar.skip {\n", | |
| " background: #f1e767;\n", | |
| " background: -moz-linear-gradient(top, #f1e767 0%, #feb645 100%);\n", | |
| " background: -webkit-gradient(linear, left top, left bottom,\n", | |
| " color-stop(0%,#f1e767),\n", | |
| " color-stop(100%,#feb645));\n", | |
| " background: -webkit-linear-gradient(top, #f1e767 0%,#feb645 100%);\n", | |
| " background: -o-linear-gradient(top, #f1e767 0%,#feb645 100%);\n", | |
| " background: -ms-linear-gradient(top, #f1e767 0%,#feb645 100%);\n", | |
| " background: linear-gradient(to bottom, #f1e767 0%,#feb645 100%);\n", | |
| " }\n", | |
| " div.nosebar.leftmost {\n", | |
| " border-radius: 4px 0 0 4px;\n", | |
| " }\n", | |
| " div.nosebar.rightmost {\n", | |
| " border-radius: 0 4px 4px 0;\n", | |
| " }\n", | |
| " div.nosefailbanner {\n", | |
| " border-radius: 4px 0 0 4px;\n", | |
| " border-left: 10px solid #cf0404;\n", | |
| " padding: 0.5ex 0em 0.5ex 1em;\n", | |
| " margin-top: 1ex;\n", | |
| " margin-bottom: 0px;\n", | |
| " }\n", | |
| " div.nosefailbanner.expanded {\n", | |
| " border-radius: 4px 4px 0 0;\n", | |
| " border-top: 10px solid #cf0404;\n", | |
| " }\n", | |
| " pre.nosetraceback {\n", | |
| " border-radius: 0 4px 4px 4px;\n", | |
| " border-left: 10px solid #cf0404;\n", | |
| " padding: 1em;\n", | |
| " margin-left: 0px;\n", | |
| " margin-top: 0px;\n", | |
| " display: none;\n", | |
| " }\n", | |
| " </style>\n", | |
| " \n", | |
| " <script>\n", | |
| " setTimeout(function () {\n", | |
| " $('.nosefailtoggle').bind(\n", | |
| " 'click',\n", | |
| " function () {\n", | |
| " $(\n", | |
| " $(this)\n", | |
| " .parent().toggleClass('expanded')\n", | |
| " .parent()\n", | |
| " .children()\n", | |
| " .filter('.nosetraceback')\n", | |
| " ).toggle();\n", | |
| " }\n", | |
| " );},\n", | |
| " 0);\n", | |
| " </script>\n", | |
| " \n", | |
| " <div class=\"noseresults\">\n", | |
| " <div class=\"nosebar fail leftmost\" style=\"width: 0%\">\n", | |
| " \n", | |
| " </div>\n", | |
| " <div class=\"nosebar skip\" style=\"width: 0%\">\n", | |
| " \n", | |
| " </div>\n", | |
| " <div class=\"nosebar pass rightmost\" style=\"width: 100%\">\n", | |
| " \n", | |
| " </div>\n", | |
| " 4/4 tests passed\n", | |
| " </div>\n", | |
| " " | |
| ], | |
| "output_type": "pyout", | |
| "prompt_number": 5, | |
| "text": [ | |
| "4/4 tests passed\n" | |
| ] | |
| } | |
| ], | |
| "prompt_number": 5 | |
| }, | |
| { | |
| "cell_type": "heading", | |
| "level": 2, | |
| "metadata": {}, | |
| "source": [ | |
| "What are the techniques?" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": {}, | |
| "source": [ | |
| "* small functions\n", | |
| "* docstrings\n", | |
| "* no mutable arguments\n", | |
| "* *avoid* side-effects\n", | |
| "* *args and **kwargs if you don't care\n", | |
| "* @decorators" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "collapsed": false, | |
| "input": [ | |
| "def log_result_of(function):\n", | |
| " \"\"\"Logs the result of the given function\"\"\"\n", | |
| " def inner(*args, **kwargs):\n", | |
| " result = function(*args, **kwargs)\n", | |
| " kwargs_repr = \", \".join(\"%s=%s\" % (k, repr(v)) for k, v in kwargs.iteritems())\n", | |
| " print \"LOG: %s(%s, %s) -> %s\" % (function.__name__, \", \".join(repr(x) for x in args), kwargs_repr, result)\n", | |
| " return result\n", | |
| "\n", | |
| " return inner\n", | |
| "\n", | |
| "@log_result_of\n", | |
| "def indent(s):\n", | |
| " return \" %s\" % s\n", | |
| "\n", | |
| "\n", | |
| "\n", | |
| "x = indent(\"foo\")\n", | |
| "\n", | |
| "print \"x is %s\" % repr(x)\n", | |
| "\n", | |
| "\n", | |
| "\", \".join([\"a\",\"b\", \"c\", \"d\"])\n" | |
| ], | |
| "language": "python", | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "output_type": "stream", | |
| "stream": "stdout", | |
| "text": [ | |
| "LOG: indent('foo', ) -> foo\n", | |
| "x is ' foo'\n" | |
| ] | |
| }, | |
| { | |
| "output_type": "pyout", | |
| "prompt_number": 34, | |
| "text": [ | |
| "'a, b, c, d'" | |
| ] | |
| } | |
| ], | |
| "prompt_number": 34 | |
| }, | |
| { | |
| "cell_type": "heading", | |
| "level": 2, | |
| "metadata": {}, | |
| "source": [ | |
| "What can help me in the standard library?" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "collapsed": false, | |
| "input": [ | |
| "import functools" | |
| ], | |
| "language": "python", | |
| "metadata": {}, | |
| "outputs": [], | |
| "prompt_number": 13 | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": {}, | |
| "source": [ | |
| "**functools.partial**\n" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "collapsed": false, | |
| "input": [ | |
| "def foo(bar, baz):\n", | |
| " print \"Bar\", bar\n", | |
| " print \"Baz\", baz\n", | |
| " print\n", | |
| " \n", | |
| "fixed_bar = functools.partial(foo, \"2\")\n", | |
| "\n", | |
| "fixed_bar(3)\n", | |
| "fixed_bar(baz=\"baz\")" | |
| ], | |
| "language": "python", | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "output_type": "stream", | |
| "stream": "stdout", | |
| "text": [ | |
| "Bar 2\n", | |
| "Baz 3\n", | |
| "\n", | |
| "Bar 2\n", | |
| "Baz baz\n", | |
| "\n" | |
| ] | |
| } | |
| ], | |
| "prompt_number": 14 | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": {}, | |
| "source": [ | |
| "**functools.wraps**" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "collapsed": true, | |
| "input": [ | |
| "def wraps(fn):\n", | |
| " fn.call_count = 0\n", | |
| " @functools.wraps(fn)\n", | |
| " def inner(*args, **kwargs):\n", | |
| " \"\"\"Count number of calls\"\"\"\n", | |
| " fn.call_count += 1\n", | |
| " return fn(*args, **kwargs)\n", | |
| " return inner\n", | |
| "\n", | |
| "@wraps\n", | |
| "def foo():\n", | |
| " \"\"\"Prints foo\"\"\"\n", | |
| " print \"foo\"\n", | |
| "\n", | |
| "foo()\n", | |
| "foo()\n", | |
| "print \"Foo doc\", foo.__doc__\n", | |
| "print \"Foo func_name\", foo.func_name" | |
| ], | |
| "language": "python", | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "output_type": "stream", | |
| "stream": "stdout", | |
| "text": [ | |
| "foo\n", | |
| "foo\n", | |
| "Foo doc Prints foo\n", | |
| "Foo func_name foo\n" | |
| ] | |
| } | |
| ], | |
| "prompt_number": 15 | |
| }, | |
| { | |
| "cell_type": "code", | |
| "collapsed": false, | |
| "input": [ | |
| "def unwrapped(fn):\n", | |
| " fn.call_count = 0\n", | |
| " def inner(*args, **kwargs):\n", | |
| " \"\"\"Count number of calls\"\"\"\n", | |
| " fn.call_count += 1\n", | |
| " return fn(*args, **kwargs)\n", | |
| " return inner\n", | |
| " \n", | |
| "@unwrapped\n", | |
| "def bar():\n", | |
| " \"\"\"Prints bar\"\"\"\n", | |
| " print \"bar\"\n", | |
| " \n", | |
| "bar()\n", | |
| "bar()\n", | |
| "print \"Bar doc\", bar.__doc__\n", | |
| "print \"Bar func_name\", bar.func_name" | |
| ], | |
| "language": "python", | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "output_type": "stream", | |
| "stream": "stdout", | |
| "text": [ | |
| "bar\n", | |
| "bar\n", | |
| "Bar doc Count number of calls\n", | |
| "Bar func_name inner\n" | |
| ] | |
| } | |
| ], | |
| "prompt_number": 16 | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": {}, | |
| "source": [ | |
| "**operator**" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "collapsed": false, | |
| "input": [ | |
| "map(operator.truth, [0, 1, None, []])" | |
| ], | |
| "language": "python", | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "output_type": "pyout", | |
| "prompt_number": 25, | |
| "text": [ | |
| "[False, True, False, False]" | |
| ] | |
| } | |
| ], | |
| "prompt_number": 25 | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": {}, | |
| "source": [ | |
| "operator.add -> x + y\n", | |
| "\n", | |
| "operator.mul -> x * y" | |
| ] | |
| }, | |
| { | |
| "cell_type": "heading", | |
| "level": 2, | |
| "metadata": {}, | |
| "source": [ | |
| "Iterators and generators" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "collapsed": false, | |
| "input": [ | |
| "class Integers(object):\n", | |
| " \n", | |
| " def __init__(self, start=0, stop=10):\n", | |
| " self.num = start\n", | |
| " self.stop = stop\n", | |
| "\n", | |
| " def __iter__(self):\n", | |
| " return self\n", | |
| "\n", | |
| " def next(self):\n", | |
| " if self.num >= self.stop:\n", | |
| " raise StopIteration()\n", | |
| " self.num += 1\n", | |
| " return self.num\n", | |
| "\n", | |
| "ints = Integers()\n", | |
| "print list(ints)" | |
| ], | |
| "language": "python", | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "output_type": "stream", | |
| "stream": "stdout", | |
| "text": [ | |
| "[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]\n" | |
| ] | |
| } | |
| ], | |
| "prompt_number": 17 | |
| }, | |
| { | |
| "cell_type": "code", | |
| "collapsed": false, | |
| "input": [ | |
| "for i in Integers(stop=3):\n", | |
| " print i" | |
| ], | |
| "language": "python", | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "output_type": "stream", | |
| "stream": "stdout", | |
| "text": [ | |
| "1\n", | |
| "2\n", | |
| "3\n" | |
| ] | |
| } | |
| ], | |
| "prompt_number": 42 | |
| }, | |
| { | |
| "cell_type": "code", | |
| "collapsed": true, | |
| "input": [ | |
| "my_range = iter(range(3))\n", | |
| "next(my_range)\n", | |
| "next(my_range)\n", | |
| "next(my_range)\n" | |
| ], | |
| "language": "python", | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "output_type": "pyout", | |
| "prompt_number": 18, | |
| "text": [ | |
| "2" | |
| ] | |
| } | |
| ], | |
| "prompt_number": 18 | |
| }, | |
| { | |
| "cell_type": "code", | |
| "collapsed": true, | |
| "input": [ | |
| "next(my_range)" | |
| ], | |
| "language": "python", | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "ename": "StopIteration", | |
| "evalue": "", | |
| "output_type": "pyerr", | |
| "traceback": [ | |
| "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m\n\u001b[0;31mStopIteration\u001b[0m Traceback (most recent call last)", | |
| "\u001b[0;32m<ipython-input-19-a0befe2dff4b>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mnext\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmy_range\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", | |
| "\u001b[0;31mStopIteration\u001b[0m: " | |
| ] | |
| } | |
| ], | |
| "prompt_number": 19 | |
| }, | |
| { | |
| "cell_type": "heading", | |
| "level": 3, | |
| "metadata": {}, | |
| "source": [ | |
| "Generators" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "collapsed": true, | |
| "input": [ | |
| "def generate_numbers(start=0, stop=10):\n", | |
| " num = start\n", | |
| " while num < stop:\n", | |
| " num += 1\n", | |
| " yield num\n", | |
| " if num ==2:\n", | |
| " return\n", | |
| "\n", | |
| "x = generate_numbers()\n", | |
| "\n", | |
| "list(x)" | |
| ], | |
| "language": "python", | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "output_type": "pyout", | |
| "prompt_number": 7, | |
| "text": [ | |
| "[1, 2]" | |
| ] | |
| } | |
| ], | |
| "prompt_number": 7 | |
| }, | |
| { | |
| "cell_type": "code", | |
| "collapsed": false, | |
| "input": [ | |
| "my_generator = generate_numbers(stop=3)\n", | |
| "next(my_generator)\n", | |
| "next(my_generator)" | |
| ], | |
| "language": "python", | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "output_type": "pyout", | |
| "prompt_number": 9, | |
| "text": [ | |
| "2" | |
| ] | |
| } | |
| ], | |
| "prompt_number": 9 | |
| }, | |
| { | |
| "cell_type": "code", | |
| "collapsed": false, | |
| "input": [ | |
| "next(my_generator)" | |
| ], | |
| "language": "python", | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "ename": "StopIteration", | |
| "evalue": "", | |
| "output_type": "pyerr", | |
| "traceback": [ | |
| "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m\n\u001b[0;31mStopIteration\u001b[0m Traceback (most recent call last)", | |
| "\u001b[0;32m<ipython-input-10-40133e33514d>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mnext\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmy_generator\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", | |
| "\u001b[0;31mStopIteration\u001b[0m: " | |
| ] | |
| } | |
| ], | |
| "prompt_number": 10 | |
| }, | |
| { | |
| "cell_type": "code", | |
| "collapsed": false, | |
| "input": [ | |
| "def numbers_with_offset(start=0, stop=10):\n", | |
| " num = start\n", | |
| " while num < stop:\n", | |
| " num += 1\n", | |
| " offset = (yield num)\n", | |
| " if offset:\n", | |
| " num += offset\n", | |
| "\n", | |
| "print list(numbers_with_offset())" | |
| ], | |
| "language": "python", | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "output_type": "stream", | |
| "stream": "stdout", | |
| "text": [ | |
| "[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]\n" | |
| ] | |
| } | |
| ], | |
| "prompt_number": 27 | |
| }, | |
| { | |
| "cell_type": "code", | |
| "collapsed": false, | |
| "input": [ | |
| "my_generator = numbers_with_offset()\n", | |
| "for i in my_generator:\n", | |
| " print i\n", | |
| " if i == 3:\n", | |
| " print my_generator.send(5)\n" | |
| ], | |
| "language": "python", | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "output_type": "stream", | |
| "stream": "stdout", | |
| "text": [ | |
| "1\n", | |
| "2\n", | |
| "3\n", | |
| "9\n", | |
| "10\n" | |
| ] | |
| } | |
| ], | |
| "prompt_number": 28 | |
| }, | |
| { | |
| "cell_type": "code", | |
| "collapsed": false, | |
| "input": [ | |
| "def fibonacci():\n", | |
| " num = 1\n", | |
| " previous = 0\n", | |
| " while True:\n", | |
| " yield num\n", | |
| " next_num = num + previous\n", | |
| " previous = num\n", | |
| " num = next_num\n", | |
| "\n", | |
| "fibber = fibonacci()\n", | |
| "next(fibber), next(fibber), next(fibber), next(fibber), next(fibber)" | |
| ], | |
| "language": "python", | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "output_type": "pyout", | |
| "prompt_number": 30, | |
| "text": [ | |
| "(1, 1, 2, 3, 5)" | |
| ] | |
| } | |
| ], | |
| "prompt_number": 30 | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": {}, | |
| "source": [ | |
| "List comprehension" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "collapsed": false, | |
| "input": [ | |
| "[x for x in range(5)]" | |
| ], | |
| "language": "python", | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "output_type": "pyout", | |
| "prompt_number": 35, | |
| "text": [ | |
| "[0, 1, 2, 3, 4]" | |
| ] | |
| } | |
| ], | |
| "prompt_number": 35 | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": {}, | |
| "source": [ | |
| "Generator expression" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "collapsed": false, | |
| "input": [ | |
| "(x for x in range(5))" | |
| ], | |
| "language": "python", | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "output_type": "pyout", | |
| "prompt_number": 36, | |
| "text": [ | |
| "<generator object <genexpr> at 0x323faf0>" | |
| ] | |
| } | |
| ], | |
| "prompt_number": 36 | |
| }, | |
| { | |
| "cell_type": "code", | |
| "collapsed": false, | |
| "input": [ | |
| "list()" | |
| ], | |
| "language": "python", | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "output_type": "pyout", | |
| "prompt_number": 37, | |
| "text": [ | |
| "[]" | |
| ] | |
| } | |
| ], | |
| "prompt_number": 37 | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": {}, | |
| "source": [ | |
| "... generator expressions can be used wherever we have ()s - no need for extra ones!" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "collapsed": false, | |
| "input": [ | |
| "list(x for x in range(5))" | |
| ], | |
| "language": "python", | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "output_type": "pyout", | |
| "prompt_number": 38, | |
| "text": [ | |
| "[0, 1, 2, 3, 4]" | |
| ] | |
| } | |
| ], | |
| "prompt_number": 38 | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": {}, | |
| "source": [ | |
| "Nested functions and closures\n", | |
| "-----------------------------" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "collapsed": false, | |
| "input": [ | |
| "def foo():\n", | |
| " a = 1\n", | |
| " b = 2\n", | |
| " def bar():\n", | |
| " return a\n", | |
| " return bar\n", | |
| "\n", | |
| "foo()()" | |
| ], | |
| "language": "python", | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "output_type": "pyout", | |
| "prompt_number": 39, | |
| "text": [ | |
| "1" | |
| ] | |
| } | |
| ], | |
| "prompt_number": 39 | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": {}, | |
| "source": [ | |
| "What happens if we form a closure over mutable variables.." | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "collapsed": false, | |
| "input": [ | |
| "def foo():\n", | |
| " a = []\n", | |
| " b = 2\n", | |
| " def bar():\n", | |
| " a.append(1)\n", | |
| " return a\n", | |
| " return bar" | |
| ], | |
| "language": "python", | |
| "metadata": {}, | |
| "outputs": [], | |
| "prompt_number": 40 | |
| }, | |
| { | |
| "cell_type": "code", | |
| "collapsed": false, | |
| "input": [ | |
| "foo()()" | |
| ], | |
| "language": "python", | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "output_type": "pyout", | |
| "prompt_number": 41, | |
| "text": [ | |
| "[1]" | |
| ] | |
| } | |
| ], | |
| "prompt_number": 41 | |
| }, | |
| { | |
| "cell_type": "code", | |
| "collapsed": false, | |
| "input": [ | |
| "b = foo()\n", | |
| "b()\n", | |
| "b()" | |
| ], | |
| "language": "python", | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "output_type": "pyout", | |
| "prompt_number": 42, | |
| "text": [ | |
| "[1, 1]" | |
| ] | |
| } | |
| ], | |
| "prompt_number": 42 | |
| }, | |
| { | |
| "cell_type": "code", | |
| "collapsed": false, | |
| "input": [ | |
| "b()" | |
| ], | |
| "language": "python", | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "output_type": "pyout", | |
| "prompt_number": 43, | |
| "text": [ | |
| "[1, 1, 1]" | |
| ] | |
| } | |
| ], | |
| "prompt_number": 43 | |
| }, | |
| { | |
| "cell_type": "code", | |
| "collapsed": false, | |
| "input": [ | |
| "b()" | |
| ], | |
| "language": "python", | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "output_type": "pyout", | |
| "prompt_number": 44, | |
| "text": [ | |
| "[1, 1, 1, 1]" | |
| ] | |
| } | |
| ], | |
| "prompt_number": 44 | |
| }, | |
| { | |
| "cell_type": "code", | |
| "collapsed": false, | |
| "input": [], | |
| "language": "python", | |
| "metadata": {}, | |
| "outputs": [] | |
| } | |
| ], | |
| "metadata": {} | |
| } | |
| ] | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment