Skip to content

Instantly share code, notes, and snippets.

@anandology
Last active December 20, 2015 13:19
Show Gist options
  • Save anandology/6137954 to your computer and use it in GitHub Desktop.
Save anandology/6137954 to your computer and use it in GitHub Desktop.
Advanced Python Workshop August 2-4, 2013 http://advancedpython.hasgeek.com/
Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Display the source blob
Display the rendered blob
Raw
{
"metadata": {
"name": "Advanced Python Workshop - Day 2"
},
"nbformat": 3,
"nbformat_minor": 0,
"worksheets": [
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Advanced Python Workshop - Day 2\n",
"[[Day 1]](http://nbviewer.ipython.org/6137954/Advanced%20Python%20Workshop%20-%20Day%201.ipynb) - \n",
"[[Day 2]](http://nbviewer.ipython.org/6137954/Advanced%20Python%20Workshop%20-%20Day%202.ipynb) - \n",
"[[Day 3]](http://nbviewer.ipython.org/6137954/Advanced%20Python%20Workshop%20-%20Day%203.ipynb)\n",
"\n",
"August 2-4, 2013 <br/>\n",
"by [Anand Chitipothu](http://anandology.com/) <br/>\n",
"<http://advancedpython.hasgeek.com/>"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Recursion**"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"def exp(x, n):\n",
" #print \"exp(%d, %d)\" % (x, n)\n",
" if n == 0:\n",
" return 1\n",
" else:\n",
" return x*exp(x, n-1)\n",
" \n",
"exp(2, 5)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "pyout",
"prompt_number": 128,
"text": [
"32"
]
}
],
"prompt_number": 128
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Implement function `mult` to multiply two numbers without using the `*` operator and loops. Assume that both the arguments will be positive integers.\n",
"\n",
" >>> mult(3, 4)\n",
" 12"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Example: Flatten List**"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Consider nested list like the one below.\n",
"\n",
" [[1, 2, [3, 4]], [5, 6, [7, [8], 9]]]\n",
"\n",
"Lets write a program to convert it into a flat list.\n",
"\n",
" [1, 2, 3, 4, 5, 6, 7, 8, 9]"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"def flatten_list(x):\n",
" y = []\n",
" for a in x:\n",
" if isinstance(a, list):\n",
" y += flatten_list(a)\n",
" else:\n",
" y.append(a)\n",
" #print \"flatten_list\", x, y\n",
" return y\n",
"\n",
"x = [[1, 2, [3, 4]], [5, 6, [7, [8], 9]]]\n",
"flatten_list(x)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "pyout",
"prompt_number": 13,
"text": [
"[1, 2, 3, 4, 5, 6, 7, 8, 9]"
]
}
],
"prompt_number": 13
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Problem:** Write a function `flatten_dict` that takes a nested dict and flattens it.\n",
"\n",
" >>> flatten_dict({\"a\": 1, \"b\": {\"x\": 2, \"y\": 3, \"z\": {\"p\": 4}}})\n",
" {\"a\": 1, \"b.x\": 2, \"b.y\": 3, \"b.z.p\": 4}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Simplest version without worrying about the prefix."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"def flatten_dict(x):\n",
" y = {}\n",
" for k, v in x.items():\n",
" if isinstance(v, dict):\n",
" y.update(flatten_dict(v))\n",
" else:\n",
" y[k] = v\n",
" return y\n",
"\n",
"flatten_dict({\"a\": 1, \"b\": {\"x\": 2, \"y\": 3, \"z\": {\"p\": 4}}})"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "pyout",
"prompt_number": 9,
"text": [
"{'a': 1, 'p': 4, 'x': 2, 'y': 3}"
]
}
],
"prompt_number": 9
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Can you try to get the prefix right?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Lets look at the `flatten_list` again. There are too many intermediate lists being created, one for each recursive call. Lets try to fix that."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"def flatten_list(x, result=None):\n",
" if result is None:\n",
" result = []\n",
" for a in x:\n",
" if isinstance(a, list):\n",
" flatten_list(a, result)\n",
" else:\n",
" result.append(a)\n",
" return result\n",
"\n",
"x = [[1, 2, [3, 4]], [5, 6, [7, [8], 9]]]\n",
"print flatten_list(x)\n",
"\n",
"print flatten_list([1, [2]])"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 18
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Example: JSON Encode**"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"def json_encode(data):\n",
" \"\"\"Takes a python data structure and converts it\n",
" into a JSON string.\n",
" \"\"\"\n",
" if isinstance(data, bool):\n",
" if data:\n",
" return \"true\"\n",
" else:\n",
" return \"false\"\n",
" elif isinstance(data, (int, float)):\n",
" return str(data)\n",
" elif isinstance(data, str):\n",
" # ignoring escaping of special chars for now\n",
" return '\"' + data + '\"'\n",
" elif isinstance(data, list):\n",
" values = [json_encode(d) for d in data]\n",
" return \"[\" + \", \".join(values) + \"]\"\n",
"\n",
"def show(x):\n",
" print \"%s\\t%s\" % (repr(x), json_encode(x))\n",
"\n",
"show(True)\n",
"show(False)\n",
"show(1)\n",
"show(1.2)\n",
"show(\"hello\")\n",
"show([1, 2, [3, 4, True]])"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"True\ttrue\n",
"False\tfalse\n",
"1\t1\n",
"1.2\t1.2\n",
"'hello'\t\"hello\"\n",
"[1, 2, [3, 4, True]]\t[1, 2, [3, 4, true]]\n"
]
}
],
"prompt_number": 129
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Can you try to extend the above function to support dictionaries as well? "
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"1"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "pyout",
"prompt_number": 52,
"text": [
"1"
]
}
],
"prompt_number": 52
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Higher Order Functions and Decorators"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"In Python, functions are first-class objects. They can be passed as arguments to other functions."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"sorted([\"python\", \"perl\", \"haskell\", \"c\", \"ocaml\"], key=len)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "pyout",
"prompt_number": 55,
"text": [
"['c', 'perl', 'ocaml', 'python', 'haskell']"
]
}
],
"prompt_number": 55
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Can we write a function that takes another function as argument?"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"def square(x): return x*x\n",
"def sum_of_squares(a, b):\n",
" squares = [square(x) for x in range(a, b)]\n",
" return sum(squares)\n",
"\n",
"sum_of_squares(0, 10)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "pyout",
"prompt_number": 56,
"text": [
"285"
]
}
],
"prompt_number": 56
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"def cube(x): return x*x*x\n",
"def sum_of_cubes(a, b):\n",
" return sum(cube(x) for x in range(a, b))\n",
"\n",
"sum_of_cubes(0, 10)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "pyout",
"prompt_number": 58,
"text": [
"2025"
]
}
],
"prompt_number": 58
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"def sigma(f, a, b):\n",
" return sum(f(x) for x in range(a, b))\n",
"\n",
"print sigma(square, 0, 10)\n",
"print sigma(cube, 0, 10)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"285\n",
"2025\n"
]
}
],
"prompt_number": 59
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"print sigma(lambda x: x**0.5, 0, 10)\n"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"19.306000526\n"
]
}
],
"prompt_number": 61
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"print sigma(lambda x: 1.0/x, 1, 100)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"5.17737751764\n"
]
}
],
"prompt_number": 64
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Problem:** Write a function to compute `unique` elements of a list. It should accept an optinal argument `key`, when supplied with a function, calls that function for each value and uses that to check the uniqueness. The order of values in the result doesn't matter.\n",
"\n",
" >>> unique([1, 2, 4, 2, 3, 1])\n",
" [1, 2, 4, 3]\n",
" >>> unique([\"Python\", \"perl\", \"python\", \"java\", \"perl\"])\n",
" [\"Python\", \"perl\", \"python\", \"java\"]\n",
" >>> unique([\"Python\", \"perl\", \"python\", \"java\", \"perl\"],\n",
" key=lambda s: s.lower())\n",
" [\"Python\", \"perl\", \"java\"]\n",
" >>> unique([\"python\", \"perl\", \"java\", \"jython\"], key=lambda s: s[0])\n",
" [\"python\", \"java\"]\n"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"def unique(values, key=None):\n",
"# if key is None:\n",
"# key = lambda x:x\n",
" d = {}\n",
" for v in values:\n",
" if key is None:\n",
" d[v] = v\n",
" else:\n",
" d[key(v)] = v\n",
" return d.values()\n",
"\n",
"print unique([\"Python\", \"perl\", \"python\", \"java\", \"perl\"])\n",
"print unique([\"python\", \"perl\", \"java\", \"jython\"], \n",
" key=lambda s:s[0])\n",
"\n",
"r1 = {\"name\": \"person 1\", \"email\": \"[email protected]\"}\n",
"r2 = {\"name\": \"person 2\", \"email\": \"[email protected]\"}\n",
"r3 = {\"name\": \"person-1\", \"email\": \"[email protected]\"}\n",
"\n",
"print unique([r1,r2,r3], lambda r:r['email'])\n"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"['Python', 'python', 'java', 'perl']\n",
"['perl', 'jython']\n",
"[{'name': 'person-1', 'email': '[email protected]'}, {'name': 'person 2', 'email': '[email protected]'}]\n"
]
}
],
"prompt_number": 72
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"f = lambda s:s[0]\n",
"def f(s): return s[0]\n",
"f(\"perl\")"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "pyout",
"prompt_number": 71,
"text": [
"'p'"
]
}
],
"prompt_number": 71
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"unique([\"a\", \"b\", \"foo\", \"bar\"], key=len)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "pyout",
"prompt_number": 73,
"text": [
"['b', 'bar']"
]
}
],
"prompt_number": 73
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now, lets look at functions that return functions."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"def add1(x): return x+1\n",
"def add2(x): return x+2\n",
"def add3(x): return x+3\n",
"def add4(x): return x+4"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 74
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"I don't want to write functions like that everytime I need one. Can we have something like this?\n",
"\n",
" add5 = make_adder(5)\n",
" print add5(6)"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"def make_adder(x):\n",
" def add(y):\n",
" return x+y\n",
" return add\n",
"\n",
"add5 = make_adder(5)\n",
"add7 = make_adder(7)\n",
"print add5(6)\n",
"print add7(6)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"11\n",
"13\n"
]
}
],
"prompt_number": 76
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Example: Tracing function calls**"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Lets looks the `exp` function that we wrote earlier. Can trace the function calls without modifying that function?\n",
"\n",
" def exp(x, n):\n",
" #print \"exp(%d, %d)\" % (x, n)\n",
" if n == 0:\n",
" return 1\n",
" else:\n",
" return x*exp(x, n-1)\n",
" \n",
" exp(2, 5)"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"def trace(f):\n",
" def g(x, n):\n",
" print \"%s(%s, %s)\" % (f.__name__, x, n)\n",
" return f(x, n)\n",
" return g\n",
"\n",
"def add(a, b): return a+b\n",
"add2 = trace(add)\n",
"print add2(2, 3)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"add(2, 3)\n",
"5\n"
]
}
],
"prompt_number": 114
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"exp(3, 4)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "pyout",
"prompt_number": 98,
"text": [
"81"
]
}
],
"prompt_number": 98
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"# let me save exp for later use.\n",
"# I'm doing this because I'm modifying it again and again. \n",
"# You probably don't need to bother about this.\n",
"orig_exp = exp\n",
"orig_json_encode = json_encode"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 130
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"exp = orig_exp\n",
"exp = trace(exp)\n",
"exp(3, 7)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"exp(3, 7)\n",
"exp(3, 6)\n",
"exp(3, 5)\n",
"exp(3, 4)\n",
"exp(3, 3)\n",
"exp(3, 2)\n",
"exp(3, 1)\n",
"exp(3, 0)\n"
]
},
{
"output_type": "pyout",
"prompt_number": 131,
"text": [
"2187"
]
}
],
"prompt_number": 131
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Lets try to improve the above trace function to format it nicely."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"indent = 0\n",
"def trace2(f):\n",
" def g(*args):\n",
" global indent\n",
" # convert args into a string\n",
" sargs = \",\".join(str(a) for a in args)\n",
" print \"| \" * indent + \"|-- %s(%s)\" % (f.__name__, sargs)\n",
" indent += 1\n",
" value = f(*args)\n",
" indent -= 1\n",
" return value\n",
" return g"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 132
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"exp = orig_exp\n",
"exp = trace2(exp)\n",
"print exp(3, 5)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"|-- exp(3,5)\n",
"| |-- exp(3,4)\n",
"| | |-- exp(3,3)\n",
"| | | |-- exp(3,2)\n",
"| | | | |-- exp(3,1)\n",
"| | | | | |-- exp(3,0)\n",
"243\n"
]
}
],
"prompt_number": 133
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"json_encode = orig_json_encode\n",
"json_encode = trace2(json_encode)"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 134
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"json_encode([1, 2, 3])"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"|-- json_encode([1, 2, 3])\n",
"| |-- json_encode(1)\n",
"| |-- json_encode(2)\n",
"| |-- json_encode(3)\n"
]
},
{
"output_type": "pyout",
"prompt_number": 135,
"text": [
"'[1, 2, 3]'"
]
}
],
"prompt_number": 135
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"json_encode([1, 2, 3, [[2, 3], 'hello']])"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"|-- json_encode([1, 2, 3, [[2, 3], 'hello']])\n",
"| |-- json_encode(1)\n",
"| |-- json_encode(2)\n",
"| |-- json_encode(3)\n",
"| |-- json_encode([[2, 3], 'hello'])\n",
"| | |-- json_encode([2, 3])\n",
"| | | |-- json_encode(2)\n",
"| | | |-- json_encode(3)\n",
"| | |-- json_encode(hello)\n"
]
},
{
"output_type": "pyout",
"prompt_number": 136,
"text": [
"'[1, 2, 3, [[2, 3], \"hello\"]]'"
]
}
],
"prompt_number": 136
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Problem:** Write a higher-order function `profile` that takes a function as arguments and returns a new function that prints the amount of time it took to execute it.\n",
"\n",
" def profile(f):\n",
" def g(n):\n",
" ...\n",
" return g\n",
"\n",
" def timepass(n):\n",
" sum = 0\n",
" for i in range(n):\n",
" for j in range(n):\n",
" sum += i*j\n",
" return sum\n",
"\n",
" timepass = profile(timepass)\n",
" print timepass() # should print both the time taken and the return value\n",
"\n",
"Hint: `time.time()` will give the current time as a floating point number."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"import time\n",
"print time.time()"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"1375515104.43\n"
]
}
],
"prompt_number": 137
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The functions like trace, profile are called decoratos and Python has a special syntax for applying them."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"@trace2\n",
"def fib(n):\n",
" if n == 0 or n == 1:\n",
" return 1\n",
" else:\n",
" return fib(n-1) + fib(n-2)\n",
" \n",
"# @trace2 is equivalant to:\n",
"# fib = trace2(fib)\n",
"fib(5)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"|-- fib(5)\n",
"| |-- fib(4)\n",
"| | |-- fib(3)\n",
"| | | |-- fib(2)\n",
"| | | | |-- fib(1)\n",
"| | | | |-- fib(0)\n",
"| | | |-- fib(1)\n",
"| | |-- fib(2)\n",
"| | | |-- fib(1)\n",
"| | | |-- fib(0)\n",
"| |-- fib(3)\n",
"| | |-- fib(2)\n",
"| | | |-- fib(1)\n",
"| | | |-- fib(0)\n",
"| | |-- fib(1)\n"
]
},
{
"output_type": "pyout",
"prompt_number": 141,
"text": [
"8"
]
}
],
"prompt_number": 141
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Example: Memoize**"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"import functools\n",
"def memoize(f):\n",
" cache = {}\n",
" # This makes the function g look like the given function f.\n",
" # The __name__, __doc__ etc. will be copied.\n",
" @functools.wraps(f)\n",
" def g(n):\n",
" if n not in cache:\n",
" cache[n] = f(n)\n",
" return cache[n]\n",
" return g\n",
"\n",
"@trace2\n",
"@memoize\n",
"def fib2(n):\n",
" if n == 0 or n == 1:\n",
" return 1\n",
" else:\n",
" return fib2(n-1) + fib2(n-2)\n",
" \n",
"fib2(5)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"|-- fib2(5)\n",
"| |-- fib2(4)\n",
"| | |-- fib2(3)\n",
"| | | |-- fib2(2)\n",
"| | | | |-- fib2(1)\n",
"| | | | |-- fib2(0)\n",
"| | | |-- fib2(1)\n",
"| | |-- fib2(2)\n",
"| |-- fib2(3)\n"
]
},
{
"output_type": "pyout",
"prompt_number": 145,
"text": [
"8"
]
}
],
"prompt_number": 145
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Problem:** Write a decorator `vectorize`, that takes a function f as argument and returns a new function that takes a list as argument and calls f for each value and returns the list of results back.\n",
"\n",
" >>> def square(x): \n",
" ... return x*x\n",
" ...\n",
" >>> squares = vectorize(square)\n",
" >>> squares([1,2,3,4])\n",
" [1,4,9,16]\n",
"\n",
" >>> g = vectorize(len)\n",
" >>> g([\"hello\", \"python\"])\n",
" [5, 6]\n",
"\n",
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Example: Writing command line apps using decorators**"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%%file command0.py\n",
"def command(f):\n",
" def gen_output(lines, **kwargs):\n",
" for line in lines:\n",
" for outline in f(line, **kwargs):\n",
" yield outline\n",
" \n",
" def g(filenames, **kwargs):\n",
" lines = read_lines(filenames)\n",
" #lines = [f(line, **kwargs) for line in lines]\n",
" #lines = [line for line in lines if line is not None]\n",
" outlines = gen_output(lines, **kwargs)\n",
" print_lines(outlines)\n",
" return g\n",
"\n",
"def read_lines(filenames):\n",
" return (line for f in filenames for line in open(f))\n",
"\n",
"def print_lines(lines):\n",
" for line in lines:\n",
" print line.strip(\"\\n\")"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"Overwriting command0.py\n"
]
}
],
"prompt_number": 174
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%%file uppercase.py\n",
"from command0 import command\n",
"import sys\n",
"\n",
"@command\n",
"def uppercase(line):\n",
" yield line.upper()\n",
"\n",
"if __name__ == \"__main__\":\n",
" uppercase(sys.argv[1:])"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"Overwriting uppercase.py\n"
]
}
],
"prompt_number": 170
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"!python uppercase.py uppercase.py"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"FROM COMMAND0 IMPORT COMMAND\r\n",
"IMPORT SYS\r\n",
"\r\n",
"@COMMAND\r\n",
"DEF UPPERCASE(LINE):\r\n",
" YIELD LINE.UPPER()\r\n",
"\r\n",
"IF __NAME__ == \"__MAIN__\":\r\n",
" UPPERCASE(SYS.ARGV[1:])\r\n"
]
}
],
"prompt_number": 171
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"How do we implement grep?"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%%file grep0.py\n",
"import sys\n",
"from command0 import command\n",
"\n",
"@command\n",
"def grep(line, pattern):\n",
" if pattern in line:\n",
" yield line\n",
" \n",
"if __name__ == \"__main__\":\n",
" pattern = sys.argv[1]\n",
" filenames = sys.argv[2:]\n",
" grep(filenames, pattern=pattern)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"Overwriting grep0.py\n"
]
}
],
"prompt_number": 172
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"!python grep0.py def command0.py"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"def command(f):\r\n",
" def gen_output(lines, **kwargs):\r\n",
" def g(filenames, **kwargs):\r\n",
"def read_lines(filenames):\r\n",
"def print_lines(lines):\r\n"
]
}
],
"prompt_number": 173
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Example: Web Framework**"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Lets build a simple web framework like thing with all the moving parts except the network."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%%file bicycle.py\n",
"\n",
"before_hooks = []\n",
"\n",
"def default_notfound():\n",
" return \"Not Found\"\n",
"\n",
"notfound = default_notfound\n",
"\n",
"def request(url):\n",
" \"\"\"calls the approriate controller to handle the given URL.\n",
" If there is no controller, then \"Not Found\" is returned.\n",
" \"\"\"\n",
" #print \"request\", mapping\n",
" for h in before_hooks:\n",
" h(url)\n",
" \n",
" for pattern, f in mapping:\n",
" if pattern == url:\n",
" return f()\n",
" \n",
" return notfound()\n",
"\n",
"def before_request(f):\n",
" before_hooks.append(f)\n",
" return f\n",
"\n",
"mapping = []\n",
"def route(path):\n",
" print \"route\", path, mapping\n",
" def decorator(f):\n",
" mapping.append((path, f))\n",
" print \"decorator\", f, mapping\n",
" return f\n",
" return decorator\n",
"\n",
"def on_notfound(f):\n",
" global notfound\n",
" notfound = f\n",
" return f"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"Overwriting bicycle.py\n"
]
}
],
"prompt_number": 230
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%%file app1.py\n",
"from bicycle import request, before_request, route, on_notfound\n",
"import time\n",
"\n",
"@before_request\n",
"def log_request(url):\n",
" print\n",
" print time.asctime(), url\n",
" \n",
"#@route(\"/\")\n",
"#def index():\n",
"# return \"Welcome\"\n",
"\n",
"\n",
"def index():\n",
" return \"Welcome\"\n",
"\n",
"decor = route(\"/\")\n",
"index = decor(index)\n",
"\n",
"@route(\"/login\")\n",
"def login():\n",
" return \"Please login to continue.\\nLOGIN: ____\\nPASSWORD:____\\nSUBMIT\"\n",
"\n",
"\n",
"@on_notfound\n",
"def notfound():\n",
" return \"404 - This is not the page you are looking for.\"\n",
"\n"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"Overwriting app1.py\n"
]
}
],
"prompt_number": 233
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%%file client1.py\n",
"# This is a simple client for our web app\n",
"# In real-world the requests come from a web browser\n",
"import app1\n",
"from bicycle import request\n",
"\n",
"def main():\n",
" print request(\"/\")\n",
" print request(\"/login\") \n",
" \n",
"if __name__ == \"__main__\":\n",
" main()"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"Writing client1.py\n"
]
}
],
"prompt_number": 234
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"!python client1.py"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"route / []\r\n",
"decorator <function index at 0x10046ec80> [('/', <function index at 0x10046ec80>)]\r\n",
"route /login [('/', <function index at 0x10046ec80>)]\r\n",
"decorator <function login at 0x10046ede8> [('/', <function index at 0x10046ec80>), ('/login', <function login at 0x10046ede8>)]\r\n",
"\r\n",
"Sat Aug 3 16:58:25 2013 /\r\n",
"Welcome\r\n",
"\r\n",
"Sat Aug 3 16:58:25 2013 /login\r\n",
"Please login to continue.\r\n",
"LOGIN: ____\r\n",
"PASSWORD:____\r\n",
"SUBMIT\r\n"
]
}
],
"prompt_number": 235
},
{
"cell_type": "code",
"collapsed": false,
"input": [],
"language": "python",
"metadata": {},
"outputs": []
}
],
"metadata": {}
}
]
}
Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment