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
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 3"
},
"nbformat": 3,
"nbformat_minor": 0,
"worksheets": [
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Advanced Python Workshop - Day 3\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": "code",
"collapsed": false,
"input": [
"def count_words(fileobj):\n",
" return sum(len(line.strip().split()) for line in fileobj.readlines())"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 8
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"!ls *.py"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"app1.py client1.py count_functions.py count_words.py echo.py grep0.py uppercase.py\r\n",
"bicycle.py command0.py count_lines.py date.py grep.py square.py\r\n"
]
}
],
"prompt_number": 5
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"count_words(open(\"grep.py\"))"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "pyout",
"prompt_number": 6,
"text": [
"61"
]
}
],
"prompt_number": 6
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"!wc -w grep.py"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
" 61 grep.py\r\n"
]
}
],
"prompt_number": 7
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"class FakeFile:\n",
" def read(self):\n",
" return \"1 one\\n2 two\\n3 three\\n\"\n",
" \n",
" def readlines(self):\n",
" return [\"1 one\\n\", \"2 two\\n\", \"3 three\\n\"]\n",
" \n",
"print count_words(FakeFile())"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"6\n"
]
}
],
"prompt_number": 9
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Problem:** Write a class `UpperCaseFile`, that takes a fileobj as argument and behaves like a file, but returns everything in uppercase when read.\n",
"\n",
"\n",
" f = UpperCaseFile(open(\"numbers.txt\"))\n",
" print f.readline() # should give \"1 ONE\\n\"\n",
"\n",
" f = UpperCaseFile(open(\"numbers.txt\"))\n",
" print count_words(f)\n",
"\n",
"\n",
" class UpperCaseFile:\n",
" def __init__(self, fileobj):\n",
" pass\n",
" \n",
" def read(self):\n",
" pass\n",
" \n",
" def readline(self):\n",
" pass\n",
" \n",
" def readlines(self):\n",
" pass\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Example: Point class**"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"class Point:\n",
" def __init__(self, x, y):\n",
" self.x = x\n",
" self.y = y\n",
" \n",
" def __str__(self):\n",
" return \"(%d, %d)\" % (self.x, self.y)\n",
"\n",
"p1 = Point(1, 2)\n",
"p2 = Point(2, 3)\n",
"\n",
"print p1.x, p1.y\n",
"print p2.x, p2.y\n",
"\n",
"print p1"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"1 2\n",
"2 3\n",
"(1, 2)\n"
]
}
],
"prompt_number": 14
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Problem:** Write a class `Timer` to measure time.\n",
"\n",
" t = Timer()\n",
" t.start()\n",
" timepass()\n",
" t.stop()\n",
" print \"took\", t.elapsed, \"seconds\"\n",
"\n",
"Can you implement these as functions instead of class? \n",
"\n",
" start_timer()\n",
" timepass()\n",
" stop_timer()\n",
" print \"took\", elapsed, \"seconds\"\n",
"\n",
"Are there any benefits of writing it as a class?"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"import time\n",
"t0 = 0\n",
"elapsed = 0\n",
"\n",
"def start_timer():\n",
" global t0\n",
" t0 = time.time()\n",
"\n",
"def stop_timer():\n",
" global elapsed\n",
" t1 = time.time()\n",
" elapsed = t1-t0\n",
"\n",
"def timepass1():\n",
" start_timer()\n",
" for i in range(10000):\n",
" x = i**100\n",
" stop_timer()\n",
" print \"timepass1 took\", elapsed, \"seconds\"\n",
"\n",
"def timepass2():\n",
" start_timer()\n",
" for i in range(10):\n",
" timepass1()\n",
" stop_timer()\n",
" print \"timepass2 took\", elapsed, \"seconds\"\n",
" \n",
"timepass1()\n",
"timepass2()"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"timepass1 took 0.0382990837097 seconds\n",
"timepass1 took 0.038852930069 seconds\n",
"timepass1 took"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" 0.0377581119537 seconds\n",
"timepass1 took 0.0365238189697 seconds\n",
"timepass1 took"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" 0.0356030464172 seconds\n",
"timepass1 took 0.0408570766449 seconds\n",
"timepass1 took"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" 0.035933971405 seconds\n",
"timepass1 took 0.0426700115204 seconds\n",
"timepass1 took"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" 0.035710811615 seconds\n",
"timepass1 took 0.0387251377106 seconds\n",
"timepass1 took"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" 0.035640001297 seconds\n",
"timepass2 took 0.0363600254059 seconds\n"
]
}
],
"prompt_number": 23
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"import time\n",
"\n",
"class Timer:\n",
" def start(self):\n",
" self.t0 = time.time()\n",
" \n",
" def stop(self):\n",
" self.elapsed = time.time() - self.t0\n",
"\n",
"def timepass1():\n",
" t = Timer()\n",
" t.start()\n",
" for i in range(10000):\n",
" x = i**100\n",
" t.stop()\n",
" print \"timepass1 took\", t.elapsed, \"seconds\"\n",
"\n",
"def timepass2():\n",
" t = Timer()\n",
" t.start()\n",
" for i in range(10):\n",
" timepass1()\n",
" t.stop()\n",
" print \"timepass2 took\", t.elapsed, \"seconds\"\n",
" \n",
"timepass1()\n",
"timepass2()"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"timepass1 took 0.0437519550323 seconds\n",
"timepass1 took 0.0390751361847 seconds\n",
"timepass1 took"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" 0.0376250743866 seconds\n",
"timepass1 took 0.0366141796112 seconds\n",
"timepass1 took"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" 0.0356080532074 seconds\n",
"timepass1 took 0.0400488376617 seconds\n",
"timepass1 took"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" 0.0352680683136 seconds\n",
"timepass1 took 0.0379021167755 seconds\n",
"timepass1 took"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" 0.0354430675507 seconds\n",
"timepass1 took 0.0385251045227 seconds\n",
"timepass1 took"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" 0.0365009307861 seconds\n",
"timepass2 took 0.376410007477 seconds\n"
]
}
],
"prompt_number": 24
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"class Foo:\n",
" x = 1\n",
"f1 = Foo()\n",
"f2 = Foo()"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 28
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"Foo"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "pyout",
"prompt_number": 26,
"text": [
"__main__.Foo"
]
}
],
"prompt_number": 26
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"Foo.__dict__"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "pyout",
"prompt_number": 27,
"text": [
"{'__doc__': None, '__module__': '__main__', 'x': 1}"
]
}
],
"prompt_number": 27
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"f1.__dict__"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "pyout",
"prompt_number": 29,
"text": [
"{}"
]
}
],
"prompt_number": 29
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"print Foo.x, f1.x, f2.x"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"1 1 1\n"
]
}
],
"prompt_number": 30
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"f2.x = 2\n",
"print Foo.x, f1.x, f2.x"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"1 1 2\n"
]
}
],
"prompt_number": 32
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"f2.__dict__"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "pyout",
"prompt_number": 33,
"text": [
"{'x': 2}"
]
}
],
"prompt_number": 33
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"Foo.x = 3\n",
"print Foo.x, f1.x, f2.x"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"3 3 2\n"
]
}
],
"prompt_number": 34
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"Foo.__dict__"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "pyout",
"prompt_number": 35,
"text": [
"{'__doc__': None, '__module__': '__main__', 'x': 3}"
]
}
],
"prompt_number": 35
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"f1.__dict__"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "pyout",
"prompt_number": 36,
"text": [
"{}"
]
}
],
"prompt_number": 36
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Example 2**"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"class Foo(object):\n",
" x = 1\n",
"\n",
" def getx(self):\n",
" return self.x\n",
"\n",
"f = Foo()\n",
"print f.getx()"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"1\n"
]
}
],
"prompt_number": 38
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"Foo.getx"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "pyout",
"prompt_number": 39,
"text": [
"<unbound method Foo.getx>"
]
}
],
"prompt_number": 39
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"Foo.getx(f)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "pyout",
"prompt_number": 40,
"text": [
"1"
]
}
],
"prompt_number": 40
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"class Bar:\n",
" pass\n",
"\n",
"Bar.x = 1\n",
"Bar.y = 2\n",
"b = Bar()\n",
"print b.x, b.y"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"1 2\n"
]
}
],
"prompt_number": 41
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"c = Bar()\n",
"print c.x, c.y"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"1 2\n"
]
}
],
"prompt_number": 42
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"b.x = 11\n",
"print b.x, c.x"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"11 1\n"
]
}
],
"prompt_number": 43
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"class creation."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"class Foo(object):\n",
" x = 1\n",
"\n",
" def getx(self):\n",
" return self.x"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 44
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"Foo"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "pyout",
"prompt_number": 45,
"text": [
"__main__.Foo"
]
}
],
"prompt_number": 45
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"print Foo.x, Foo.getx"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"1 <unbound method Foo.getx>\n"
]
}
],
"prompt_number": 46
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"Foo2 = type(\"Foo2\", (), {\"x\": 1, \"getx\": lambda self: self.x})"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 48
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Emulating Container Types**"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"len(\"hello\")"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "pyout",
"prompt_number": 50,
"text": [
"5"
]
}
],
"prompt_number": 50
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"len([1, 2, 3])"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "pyout",
"prompt_number": 51,
"text": [
"3"
]
}
],
"prompt_number": 51
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"class yrange:\n",
" def __init__(self, n):\n",
" self.n = n\n",
" \n",
" def __len__(self):\n",
" return self.n\n",
" \n",
"y = yrange(10)\n",
"print len(y)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"10\n"
]
}
],
"prompt_number": 54
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"s = \"hello\"\n",
"a = [1, 2, 3]\n",
"print s[0], a[2]"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"h 3\n"
]
}
],
"prompt_number": 55
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"class yrange:\n",
" def __init__(self, n):\n",
" self.n = n\n",
" \n",
" def __len__(self):\n",
" print \"__len__\" \n",
" return self.n\n",
" \n",
" def __getitem__(self, i):\n",
" print \"__getitem__\", i\n",
" if 0 <= i < self.n:\n",
" return i\n",
" else:\n",
" raise IndexError(i)\n",
" \n",
" def __contains__(self, value):\n",
" print \"__contains__\", value\n",
" return 0 <= value < self.n\n",
" \n",
" \n",
"y = yrange(10)\n",
"print y[5]"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"__getitem__ 5\n",
"5\n"
]
}
],
"prompt_number": 68
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Problem:** The above implementation of `yrange` assumes that the begin is always 0. Can you write a class `zrange` that takes both begin and end and supports `len` and `[]` operator.\n",
"\n",
" z = zrange(3, 8)\n",
" print len(z) # 5\n",
" print z[1] # 4"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"y = yrange(10)\n",
"-1 in y"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"__contains__ -1\n"
]
},
{
"output_type": "pyout",
"prompt_number": 69,
"text": [
"False"
]
}
],
"prompt_number": 69
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Problem:** Write a class `Folder` to give a dictionary like interface to a folder on disk. \n",
"\n",
" d = Folder(\"foo\")\n",
" print len(d) # should print the number of files in foo\n",
" \n",
" print d['a.txt'] # should print the contents of foo/a.txt\n",
" d['a.txt'] = 'hello, world' # overwrite a.txt with 'hello, world'\n",
"\n",
" print 'b.txt' in d # print True if foo/b.txt exists\n",
"\n",
"Hints:\n",
"\n",
"* os.listdir\n",
"* os.path.exists\n",
"* os.path.isdir\n",
"* os.path.isfile\n",
"* os.path.join"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"import os\n",
"class Folder:\n",
" def __init__(self, path):\n",
" self.path = path\n",
" \n",
" def __getitem__(self, filename):\n",
" path = os.path.join(self.path, filename)\n",
" return open(path).read()"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 70
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Customizing attribute access**"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"class Foo:\n",
" def __getattr__(self, name):\n",
" return name.upper()\n",
" \n",
"f = Foo()"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 71
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"f.x"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "pyout",
"prompt_number": 72,
"text": [
"'X'"
]
}
],
"prompt_number": 72
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"!mkdir -p foo && echo hello world > foo/a.txt"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 75
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"class Folder2:\n",
" def __init__(self, path):\n",
" self.path = path\n",
" \n",
" def __getattr__(self, name):\n",
" filename = name + \".txt\"\n",
" path = os.path.join(self.path, filename)\n",
" return open(path).read()\n",
" \n",
"foo = Folder2(\"foo\")\n",
"print foo.a"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"hello world\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"\n"
]
}
],
"prompt_number": 76
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Emulating Functions**"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"class Adder:\n",
" def __init__(self, x):\n",
" self.x = x\n",
" \n",
" def __call__(self, y):\n",
" return self.x + y\n",
" \n",
"add5 = Adder(5)\n",
"print add5(6)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"11\n"
]
}
],
"prompt_number": 78
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Problem:** Implement the `memoize` function that we did earlier as a class?"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"class memoize:\n",
" def __init__(self, f):\n",
" self.f = f\n",
" self.cache = {}\n",
" \n",
" def __call__(self, n):\n",
" if n not in self.cache:\n",
" self.cache[n] = self.f(n)\n",
" return self.cache[n]\n",
" \n",
"@memoize\n",
"def square(x):\n",
" print \"square(%d)\" % x\n",
" return x*x\n",
"print square(2)\n",
"print square(2)\n",
"print square(2)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"square(2)\n",
"4\n",
"4\n",
"4\n"
]
}
],
"prompt_number": 81
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"square"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "pyout",
"prompt_number": 80,
"text": [
"<__main__.memoize instance at 0x102720998>"
]
}
],
"prompt_number": 80
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Customizing Numeric Operations**"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"class Point:\n",
" def __init__(self, x, y):\n",
" self.x = x\n",
" self.y = y\n",
" \n",
" def __add__(self, p2):\n",
" return Point(self.x + p2.x, self.y + p2.y)\n",
" \n",
" def __str__(self):\n",
" return \"(%d, %d)\" % (self.x, self.y)\n",
"\n",
"p1 = Point(1, 3)\n",
"p2 = Point(4, 4)\n",
"print p1 + p2"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"(5, 7)\n"
]
}
],
"prompt_number": 86
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Problem:** Implement `__mul__` to scale a point by a number.\n",
"\n",
" print Point(1, 2) * 5 # (5, 10)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**`str` and `repr`**"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"print 1, \"1\"\n",
"print str(1), str(\"1\")\n",
"print repr(1), repr(\"1\")"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"1 1\n",
"1 1\n",
"1 '1'\n"
]
}
],
"prompt_number": 88
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"[1, 'hello']"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "pyout",
"prompt_number": 89,
"text": [
"[1, 'hello']"
]
}
],
"prompt_number": 89
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"p1 = Point(2, 3)"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 90
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"print p1"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"(2, 3)\n"
]
}
],
"prompt_number": 92
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"[p1]"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "pyout",
"prompt_number": 93,
"text": [
"[<__main__.Point instance at 0x102725ea8>]"
]
}
],
"prompt_number": 93
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"class Point:\n",
" def __init__(self, x, y):\n",
" self.x = x\n",
" self.y = y\n",
" \n",
" def __add__(self, p2):\n",
" return Point(self.x + p2.x, self.y + p2.y)\n",
" \n",
" def __str__(self):\n",
" return \"(%d, %d)\" % (self.x, self.y)\n",
"\n",
" def __repr__(self):\n",
" return \"Point(%d, %d)\" % (self.x, self.y)\n",
"\n",
"p1 = Point(1, 3)\n",
"p2 = Point(4, 4)\n",
"print [p1, p2, p1+p2]"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"[Point(1, 3), Point(4, 4), Point(5, 7)]\n"
]
}
],
"prompt_number": 95
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Properties**"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"class Person:\n",
" def __init__(self, fullname, phone):\n",
" self.fullname = fullname\n",
" self.phone = phone\n",
" \n",
" def __repr__(self):\n",
" return \"Person(%r, %r)\" % (self.fullname, self.phone)\n",
" \n",
"p = Person(\"Joe\", \"1234567890\")\n",
"print p"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"Person('Joe', '1234567890')\n"
]
}
],
"prompt_number": 99
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Lets say this is the first implementation of Person class. This allows modifying fullname and phone number and there is no no validation."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"p.phone = \"bad-number\"\n",
"print p"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"Person('Joe', 'bad-number')\n"
]
}
],
"prompt_number": 101
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Lets say we want to validate phone number on assignment. "
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"class Person(object):\n",
" def __init__(self, fullname, phone):\n",
" self.fullname = fullname\n",
" self._phone = phone\n",
" \n",
" @property\n",
" def phone(self):\n",
" return self._phone\n",
" \n",
" @phone.setter\n",
" def phone(self, value):\n",
" if len(value) == 10:\n",
" self.value = value\n",
" else:\n",
" raise ValueError(\"Invalid phone number %r\" % value)\n",
" \n",
" def __repr__(self):\n",
" return \"Person(%r, %r)\" % (self.fullname, self.phone)\n",
" \n",
"p = Person(\"Joe\", \"1234567890\")\n",
"print p"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"Person('Joe', '1234567890')\n"
]
}
],
"prompt_number": 129
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"p.phone"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "pyout",
"prompt_number": 125,
"text": [
"'1234567890'"
]
}
],
"prompt_number": 125
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"p.phone = \"bad\""
],
"language": "python",
"metadata": {},
"outputs": [
{
"ename": "ValueError",
"evalue": "Invalid phone number 'bad'",
"output_type": "pyerr",
"traceback": [
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m\n\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)",
"\u001b[0;32m<ipython-input-127-19cd20de0879>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mphone\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m\"bad\"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
"\u001b[0;32m<ipython-input-124-08b7b0c1bb81>\u001b[0m in \u001b[0;36mset_phone\u001b[0;34m(self, value)\u001b[0m\n\u001b[1;32m 11\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mvalue\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mvalue\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 12\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 13\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mValueError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"Invalid phone number %r\"\u001b[0m \u001b[0;34m%\u001b[0m \u001b[0mvalue\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 14\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 15\u001b[0m \u001b[0mphone\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mproperty\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mget_phone\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mset_phone\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;31mValueError\u001b[0m: Invalid phone number 'bad'"
]
}
],
"prompt_number": 127
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Problem** Change the Person class to take `firstname` and `lastname` as argumetns instead of `fullname` and implement `fullname` as a property."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**`staticmethod` and `classmethod`**"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"class Point:\n",
" def __init__(self, x, y):\n",
" self.x = x\n",
" self.y = y\n",
" \n",
" def __repr__(self):\n",
" return \"Point(%r, %r)\" % (self.x, self.y)\n",
" \n",
" @staticmethod\n",
" def from_file(filename):\n",
" \"\"\"Constructs a Point from the given file.\n",
" \"\"\"\n",
" x, y = open(filename).read().split()\n",
" return Point(int(x), int(y))\n",
" "
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 139
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%%file p1.txt\n",
"1 2"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"Overwriting p1.txt\n"
]
}
],
"prompt_number": 140
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"Point.from_file(\"p1.txt\")"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "pyout",
"prompt_number": 141,
"text": [
"Point(1, 2)"
]
}
],
"prompt_number": 141
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"import datetime\n",
"d = datetime.datetime.now()"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 143
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"d"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "pyout",
"prompt_number": 144,
"text": [
"datetime.datetime(2013, 8, 4, 14, 54, 31, 326448)"
]
}
],
"prompt_number": 144
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"`now` is a classmethod. It gets the class as argumet and uses that to constuct object."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"class DT(datetime.datetime): pass"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 145
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"DT.now()"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "pyout",
"prompt_number": 146,
"text": [
"DT(2013, 8, 4, 14, 55, 35, 126903)"
]
}
],
"prompt_number": 146
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"class Point2:\n",
" def __init__(self, x, y):\n",
" self.x = x\n",
" self.y = y\n",
" \n",
" def __repr__(self):\n",
" return \"%s(%r, %r)\" % (self.__class__.__name__, self.x, self.y)\n",
" \n",
" @classmethod\n",
" def from_file(klass, filename):\n",
" \"\"\"Constructs a Point from the given file.\n",
" \"\"\"\n",
" x, y = open(filename).read().split()\n",
" return klass(int(x), int(y))\n",
" "
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 149
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"Point2.from_file(\"p1.txt\")"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "pyout",
"prompt_number": 150,
"text": [
"Point2(1, 2)"
]
}
],
"prompt_number": 150
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"class Point22(Point2): pass\n",
"\n",
"Point22.from_file(\"p1.txt\")"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "pyout",
"prompt_number": 151,
"text": [
"Point22(1, 2)"
]
}
],
"prompt_number": 151
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Old-style and new-style classes**"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"type(1)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "pyout",
"prompt_number": 152,
"text": [
"int"
]
}
],
"prompt_number": 152
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"type(\"hello\")"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "pyout",
"prompt_number": 153,
"text": [
"str"
]
}
],
"prompt_number": 153
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"type(int)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "pyout",
"prompt_number": 154,
"text": [
"type"
]
}
],
"prompt_number": 154
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"class Foo: pass\n",
"f = Foo()\n",
"type(f)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "pyout",
"prompt_number": 156,
"text": [
"instance"
]
}
],
"prompt_number": 156
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"class Bar: pass\n",
"b = Bar()\n",
"type(b)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "pyout",
"prompt_number": 157,
"text": [
"instance"
]
}
],
"prompt_number": 157
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"type(Bar)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "pyout",
"prompt_number": 158,
"text": [
"classobj"
]
}
],
"prompt_number": 158
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"class Foo2(object): pass\n",
"f2 = Foo2()\n",
"type(f2)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "pyout",
"prompt_number": 159,
"text": [
"__main__.Foo2"
]
}
],
"prompt_number": 159
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Foo2 is a new-style class because it is extending from object. For new-style classes, type returns the class itself."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"class Foo:\n",
" def __len__(self): return 10\n",
" \n",
"f = Foo()\n",
"print len(f)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"10\n"
]
}
],
"prompt_number": 160
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"f.__len__ = lambda: 1000"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 161
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"len(f)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "pyout",
"prompt_number": 162,
"text": [
"1000"
]
}
],
"prompt_number": 162
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"class Bar(object): \n",
" def __len__(self): return 10\n",
" \n",
"b = Bar()\n",
"print len(b) \n",
"b.__len__ = lambda: 1000\n",
"print len(b)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"10\n",
"10\n"
]
}
],
"prompt_number": 163
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Difference in behavior with multiple inheritance."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"class A:\n",
" def f(self):\n",
" print \"A.f\"\n",
" \n",
"class B1(A): pass\n",
"\n",
"class B2:\n",
" def f(self):\n",
" print \"B2.f\"\n",
" \n",
"class C(B1, B2):\n",
" pass\n",
"\n",
"c = C()\n",
"c.f()"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"A.f\n"
]
}
],
"prompt_number": 172
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now lets try with new-style classes."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"class A(object):\n",
" def f(self):\n",
" print \"A.f\"\n",
" \n",
"class B1(A): pass\n",
"\n",
"class B2(object):\n",
" def f(self):\n",
" print \"B2.f\"\n",
" \n",
"class C(B1, B2):\n",
" pass\n",
"\n",
"c = C()\n",
"c.f()"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"A.f\n"
]
}
],
"prompt_number": 174
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"???"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"C.__mro__"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "pyout",
"prompt_number": 175,
"text": [
"(__main__.C, __main__.B1, __main__.A, __main__.B2, object)"
]
}
],
"prompt_number": 175
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**`__slots__`**"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"class Point(object):\n",
" def __init__(self, x, y):\n",
" self.x = x\n",
" self.y = y\n",
" \n",
"p = Point(1, 2)\n",
"p.z = 4\n",
"print p.__dict__"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"{'y': 2, 'x': 1, 'z': 4}\n"
]
}
],
"prompt_number": 183
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"class Point2(object):\n",
" __slots__ = [\"x\", \"y\"]\n",
" def __init__(self, x, y):\n",
" self.x = x\n",
" self.y = y\n",
" \n",
"p2 = Point2(1, 2)\n",
"print p2"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"<__main__.Point2 object at 0x10273b9d0>\n"
]
}
],
"prompt_number": 186
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"Point2.z = 1"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 187
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"p2.__class__"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "pyout",
"prompt_number": 189,
"text": [
"__main__.Point2"
]
}
],
"prompt_number": 189
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Context Managers"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"def getdata():\n",
" return \"hello world\"\n",
"\n",
"f = open(\"a.txt\", \"w\")\n",
"f.write(getdata())\n",
"f.close()"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 190
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"What if there is an error in `getdata()`? The file won't be closed. "
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"def getdata():\n",
" return \"hello world\"\n",
"\n",
"f = open(\"a.txt\", \"w\")\n",
"try:\n",
" f.write(getdata())\n",
"finally:\n",
" f.close()"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 194
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The with statement solves that more elegantly."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"def getdata():\n",
" return \"hello world\"\n",
"\n",
"with open(\"a.txt\", \"w\") as f:\n",
" f.write(getdata())"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 197
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Example: chdir**"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"import os\n",
"class chdir:\n",
" def __init__(self, path):\n",
" self.path = path\n",
" \n",
" def __enter__(self):\n",
" print \"__enter__\"\n",
" self.old_cwd = os.getcwd()\n",
" os.chdir(self.path)\n",
" return self\n",
"\n",
" def __exit__(self, *a):\n",
" print \"__exit__\"\n",
" os.chdir(self.old_cwd)\n",
"\n",
"\n",
"print os.getcwd()\n",
"with chdir(\"/tmp\"):\n",
" print os.getcwd()\n",
"print os.getcwd()\n",
" "
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"/Users/anand/Dropbox/Trainings/2013/advancedpython-aug2013/6137954\n",
"__enter__\n",
"/private/tmp\n",
"__exit__\n",
"/Users/anand/Dropbox/Trainings/2013/advancedpython-aug2013/6137954\n"
]
}
],
"prompt_number": 204
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Problem** Write a context manager `capture_stdout` to capture stdout inside a with block.\n",
"\n",
" with capture_stdout() as buf:\n",
" print \"one\"\n",
" print \"two\"\n",
"\n",
" print \"captured\", repr(buf.getvalue())\n",
"\n",
"\n",
"Hint: use a `StringIO.StringIO`"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"from StringIO import StringIO\n",
"import sys\n",
"\n",
"class capture_stdout:\n",
" def __init__(self):\n",
" self.buf= StringIO()\n",
"\n",
" def __enter__(self):\n",
" self.old_stdout = sys.stdout\n",
" sys.stdout = self.buf\n",
" return self.buf\n",
" \n",
" def __exit__(self, type, exc, traceback):\n",
" sys.stdout = self.old_stdout\n",
" print type, exc, traceback\n",
"\n",
"with capture_stdout() as buf:\n",
" print \"one\"\n",
" print \"two\"\n",
"\n",
"print \"captured\", repr(buf.getvalue())\n",
" \n",
" "
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"None None None\n",
"captured 'one\\ntwo\\n'\n"
]
}
],
"prompt_number": 212
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Meta-classes"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"class A(object): pass"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 213
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"type(A)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "pyout",
"prompt_number": 214,
"text": [
"type"
]
}
],
"prompt_number": 214
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"class my_type(type): \n",
" def __init__(self, *a, **kw):\n",
" print \"my_type.__init__\", self, a, kw\n",
" type.__init__(self, *a, **kw)"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 217
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"class B(object): \n",
" pass\n",
"\n",
"type(B)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "pyout",
"prompt_number": 218,
"text": [
"type"
]
}
],
"prompt_number": 218
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"B2 = my_type(\"B2\", (object,), {})"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"my_type.__init__ <class '__main__.B2'> ('B2', (<type 'object'>,), {}) {}\n"
]
}
],
"prompt_number": 220
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"type(B2)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "pyout",
"prompt_number": 221,
"text": [
"__main__.my_type"
]
}
],
"prompt_number": 221
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"class B2(object):\n",
" __metaclass__ = my_type\n",
"\n",
"type(B2)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"my_type.__init__ <class '__main__.B2'> ('B2', (<type 'object'>,), {'__module__': '__main__', '__metaclass__': <class '__main__.my_type'>}) {}\n"
]
},
{
"output_type": "pyout",
"prompt_number": 222,
"text": [
"__main__.my_type"
]
}
],
"prompt_number": 222
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Metaclasses sometimes used to auto-register classes, like `@before_request` decorator that we used."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"hooks = []\n",
"\n",
"class metahook(type):\n",
" def __init__(self, *a, **kw):\n",
" hooks.append(self)\n",
" print \"adding\", self, \"to hooks\"\n",
" type.__init__(self, *a, **kw)\n",
" \n",
"class hook(object):\n",
" __metaclass__ = metahook\n",
" \n",
"class login_hook(hook):\n",
" pass\n",
"\n",
"print hooks\n"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"adding <class '__main__.hook'> to hooks\n",
"adding <class '__main__.login_hook'> to hooks\n",
"[<class '__main__.hook'>, <class '__main__.login_hook'>]\n"
]
}
],
"prompt_number": 225
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Another useful example would be to autoregister controllers for various URLs.\n",
"\n",
" class login(page):\n",
" def GET(self):\n",
" ...\n",
"\n",
" class logout(page):\n",
" def GET(self):\n",
" ...."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Another example would be to specify constraints for attributes.\n",
"\n",
" class Person(Model):\n",
" name = TextField()\n",
" email = EmailField()\n",
" phone = IntegerField()\n",
"\n",
"With this, the metaclass can enforce the types of these values."
]
},
{
"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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment