Last active
August 29, 2015 13:56
-
-
Save anandology/9223073 to your computer and use it in GitHub Desktop.
Advanced Python Training at LinkedIn -- Feb 26 - Mar 1, 2014
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"metadata": { | |
"name": "" | |
}, | |
"nbformat": 3, | |
"nbformat_minor": 0, | |
"worksheets": [ | |
{ | |
"cells": [ | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"# Advanced Python Training - Day 4\n", | |
"Linked In<br/>\n", | |
"Feb 26 - Mar 1, 2014<br/>\n", | |
"<a href=\"http://anandology.com\">Anand Chitipothu</a>" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"Classes warmup - <http://anandology.com/apy/slides/classes.html>" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"# Problem 1\n", | |
"class Foo:\n", | |
" x = 1\n", | |
"\n", | |
"f1 = Foo()\n", | |
"f2 = Foo()\n", | |
"print Foo.x, f1.x, f2.x\n", | |
"\n", | |
"f2.x = 2\n", | |
"print Foo.x, f1.x, f2.x\n", | |
"\n", | |
"Foo.x = 3\n", | |
"print Foo.x, f1.x, f2.x" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"stream": "stdout", | |
"text": [ | |
"1 1 1\n", | |
"1 1 2\n", | |
"3 3 2\n" | |
] | |
} | |
], | |
"prompt_number": 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()\n", | |
"\n", | |
"# That is equivalant to:\n", | |
"print Foo.getx(f)" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"stream": "stdout", | |
"text": [ | |
"1\n", | |
"1\n" | |
] | |
} | |
], | |
"prompt_number": 4 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"# Problem 2\n", | |
"class Foo(object):\n", | |
" x = 1\n", | |
"\n", | |
"def getx(self):\n", | |
" return self.x\n", | |
"\n", | |
"Foo.getx = getx\n", | |
"\n", | |
"f = Foo()\n", | |
"print f.getx()" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"stream": "stdout", | |
"text": [ | |
"1\n" | |
] | |
} | |
], | |
"prompt_number": 5 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"# problem 6\n", | |
"class Foo:\n", | |
" print \"hello, world\"\n", | |
" def square(x):\n", | |
" return x*x\n", | |
"\n", | |
" a = square(10)\n", | |
" print a\n", | |
"\n", | |
"print Foo.a" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"stream": "stdout", | |
"text": [ | |
"hello, world\n", | |
"100\n", | |
"100\n" | |
] | |
} | |
], | |
"prompt_number": 6 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"class Foo:\n", | |
" x = 1\n", | |
"\n", | |
"Foo.__dict__" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"metadata": {}, | |
"output_type": "pyout", | |
"prompt_number": 7, | |
"text": [ | |
"{'__doc__': None, '__module__': '__main__', 'x': 1}" | |
] | |
} | |
], | |
"prompt_number": 7 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"Foo.__dict__['y'] = 2\n", | |
"print Foo.y" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"stream": "stdout", | |
"text": [ | |
"2\n" | |
] | |
} | |
], | |
"prompt_number": 8 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"f = Foo()\n", | |
"f.__dict__" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"metadata": {}, | |
"output_type": "pyout", | |
"prompt_number": 9, | |
"text": [ | |
"{}" | |
] | |
} | |
], | |
"prompt_number": 9 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"f.__class__" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"metadata": {}, | |
"output_type": "pyout", | |
"prompt_number": 10, | |
"text": [ | |
"__main__.Foo" | |
] | |
} | |
], | |
"prompt_number": 10 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"f.x" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"metadata": {}, | |
"output_type": "pyout", | |
"prompt_number": 11, | |
"text": [ | |
"1" | |
] | |
} | |
], | |
"prompt_number": 11 | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"**ducktyping**" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"def wordcount(fileobj):\n", | |
" return len(fileobj.read().split())\n", | |
"\n", | |
"print wordcount(open(\"numbers.txt\"))" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"stream": "stdout", | |
"text": [ | |
"5\n" | |
] | |
} | |
], | |
"prompt_number": 12 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"class FakeFile:\n", | |
" def read(self):\n", | |
" return \"a b c d e\"" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [], | |
"prompt_number": 13 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"wordcount(FakeFile())" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"metadata": {}, | |
"output_type": "pyout", | |
"prompt_number": 14, | |
"text": [ | |
"5" | |
] | |
} | |
], | |
"prompt_number": 14 | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"### Special Class Methods" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"**`__str__` and `__repr__`**" | |
] | |
}, | |
{ | |
"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 \"({0}, {1})\".format(self.x, self.y)\n", | |
" \n", | |
" def __repr__(self):\n", | |
" return \"Point(x={}, y={})\".format(self.x, self.y)\n", | |
" \n", | |
"p = Point(1, 2)\n", | |
"print p\n", | |
"\n", | |
"print str(p)" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"stream": "stdout", | |
"text": [ | |
"(1, 2)\n", | |
"(1, 2)\n" | |
] | |
} | |
], | |
"prompt_number": 24 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"print \"1\", 1" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"stream": "stdout", | |
"text": [ | |
"1 1\n" | |
] | |
} | |
], | |
"prompt_number": 20 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"print repr(\"1\"), repr(1)" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"stream": "stdout", | |
"text": [ | |
"'1' 1\n" | |
] | |
} | |
], | |
"prompt_number": 21 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"[\"1\", 1]" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"metadata": {}, | |
"output_type": "pyout", | |
"prompt_number": 22, | |
"text": [ | |
"['1', 1]" | |
] | |
} | |
], | |
"prompt_number": 22 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"[p]" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"metadata": {}, | |
"output_type": "pyout", | |
"prompt_number": 25, | |
"text": [ | |
"[Point(x=1, y=2)]" | |
] | |
} | |
], | |
"prompt_number": 25 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"print p" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"stream": "stdout", | |
"text": [ | |
"(1, 2)\n" | |
] | |
} | |
], | |
"prompt_number": 26 | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"**Problem** Write a class `Person` with firstname and lastname and add str and repr." | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"**Operators**" | |
] | |
}, | |
{ | |
"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 \"({0}, {1})\".format(self.x, self.y)\n", | |
" \n", | |
" def __repr__(self):\n", | |
" return \"Point(x={}, y={})\".format(self.x, self.y)\n", | |
" \n", | |
" def __add__(self, p):\n", | |
" return Point(self.x+p.x, self.y+p.y)\n", | |
" \n", | |
"p1 = Point(2, 3)\n", | |
"p2 = Point(3, 4)\n", | |
"\n", | |
"print p1 + p2" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"stream": "stdout", | |
"text": [ | |
"(5, 7)\n" | |
] | |
} | |
], | |
"prompt_number": 31 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"x = 1\n", | |
"y = 2\n", | |
"x + y" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"metadata": {}, | |
"output_type": "pyout", | |
"prompt_number": 28, | |
"text": [ | |
"3" | |
] | |
} | |
], | |
"prompt_number": 28 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"x.__add__(y)" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"metadata": {}, | |
"output_type": "pyout", | |
"prompt_number": 29, | |
"text": [ | |
"3" | |
] | |
} | |
], | |
"prompt_number": 29 | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"**Problem** Change the `Point` class above to support `*` operator.\n", | |
" \n", | |
" >>> p = Point(2, 3)\n", | |
" >>> p * 10\n", | |
" Point(20, 30)" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"**Container types**" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"x = [\"a\", \"b\", \"c\"]\n", | |
"print x[1]" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"stream": "stdout", | |
"text": [ | |
"b\n" | |
] | |
} | |
], | |
"prompt_number": 32 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"print x.__getitem__(1)" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"stream": "stdout", | |
"text": [ | |
"b\n" | |
] | |
} | |
], | |
"prompt_number": 33 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"print len(x)" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"stream": "stdout", | |
"text": [ | |
"3\n" | |
] | |
} | |
], | |
"prompt_number": 34 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"len(\"abce\")" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"metadata": {}, | |
"output_type": "pyout", | |
"prompt_number": 35, | |
"text": [ | |
"4" | |
] | |
} | |
], | |
"prompt_number": 35 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"x.__len__()" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"metadata": {}, | |
"output_type": "pyout", | |
"prompt_number": 36, | |
"text": [ | |
"3" | |
] | |
} | |
], | |
"prompt_number": 36 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"class yrange:\n", | |
" def __init__(self, begin, end):\n", | |
" self.begin = begin\n", | |
" self.end = end\n", | |
" \n", | |
" def __len__(self):\n", | |
" return self.end - self.begin\n", | |
" \n", | |
"y = yrange(5, 10)\n", | |
"print len(y)" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"stream": "stdout", | |
"text": [ | |
"5\n" | |
] | |
} | |
], | |
"prompt_number": 39 | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"**Problem** The the above `yrange` class work like a list by adding `__getitem__` method.\n", | |
"\n", | |
" >>> y = yrange(5, 10)\n", | |
" >>> y[0]\n", | |
" 5\n", | |
" >>> y[3]\n", | |
" 8\n", | |
" >>> y[8]\n", | |
" Traceback (most recent call last):\n", | |
" ...\n", | |
" IndexError: index out of range " | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"import functools\n", | |
"\n", | |
"def itemgetter(f):\n", | |
" \"\"\"decorator to wrap __getitem__ to \n", | |
" take care of negative indices and \n", | |
" out of range errors.\n", | |
" \"\"\"\n", | |
" @functools.wraps(f)\n", | |
" def g(self, index):\n", | |
" if index < 0:\n", | |
" index = len(self) + index\n", | |
" if 0 <= index < len(self):\n", | |
" return f(self, index)\n", | |
" else:\n", | |
" raise IndexError(\"index out of range\")\n", | |
" return g\n", | |
" \n", | |
"class yrange:\n", | |
" def __init__(self, begin, end):\n", | |
" self.begin = begin\n", | |
" self.end = end\n", | |
" \n", | |
" def __len__(self):\n", | |
" return self.end - self.begin\n", | |
" \n", | |
" @itemgetter\n", | |
" def __getitem__(self, index):\n", | |
" return self.begin + index\n", | |
" \n", | |
"y = yrange(5, 10)\n", | |
"print len(y)\n", | |
"print y[0]\n", | |
"print y[3]\n", | |
"print y[-1]\n", | |
"try:\n", | |
" print y[8]\n", | |
"except IndexError, e:\n", | |
" print str(e)" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"stream": "stdout", | |
"text": [ | |
"5\n", | |
"5\n", | |
"8\n", | |
"9\n", | |
"index out of range\n" | |
] | |
} | |
], | |
"prompt_number": 45 | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"**Problem** Write a class `Node` to represent a Node in HTML tree. It should work as shown in the examples below.\n", | |
"\n", | |
" >>> input = Node(\"input\", name=\"x\", type=\"text\", value=\"3\")\n", | |
" >>> print input\n", | |
" <input type=\"text\" name=\"x\" value=\"3\"/>\n", | |
" >>> print repr(input)\n", | |
" <Node input attrs={\"type\": \"text\", \"name\": \"x\", \"value\": \"3\"}>\n", | |
" \n", | |
" >>> input['type']\n", | |
" 'text'\n", | |
" >>> input['value'] = \"10\"\n", | |
" >>> print input\n", | |
" <input type=\"text\" name=\"x\" value=\"10\"/>\n", | |
" >>> print Node(\"hr\")\n", | |
" <hr/>\n", | |
" >>> print Node(\"img\", src=\"a.jpg\")\n", | |
" <img src=\"a.jpg\"/> " | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"**Properties**" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"class Person0:\n", | |
" def __init__(self, fullname):\n", | |
" self.fullname = fullname\n", | |
" \n", | |
"def hello(p):\n", | |
" print \"Hello\", p.fullname\n", | |
" \n", | |
"# Lets say we are planning to replace the above class\n", | |
"# with the one below.\n", | |
"\n", | |
"class Person:\n", | |
" def __init__(self, firstname, lastname):\n", | |
" self.firstname = firstname\n", | |
" self.lastname = lastname\n", | |
" \n", | |
" @property\n", | |
" def fullname(self):\n", | |
" return \"{} {}\".format(self.firstname, self.lastname)\n", | |
" \n", | |
"p = Person(\"Foo\", \"Bar\")\n", | |
"hello(p)" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"stream": "stdout", | |
"text": [ | |
"Hello Foo Bar\n" | |
] | |
} | |
], | |
"prompt_number": 52 | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"**Problem** Write a class `File` that takes path as argument in the constuctor and provides basename, dirname and ext as properties.\n", | |
"\n", | |
" >>> f = File(\"/tmp/a.txt\")\n", | |
" >>> f.basename\n", | |
" 'a.txt'\n", | |
" >>> f.dirname\n", | |
" '/tmp'\n", | |
" >>> f.ext\n", | |
" 'txt'" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"import re\n", | |
"class Person(object):\n", | |
" def __init__(self, firstname, lastname, phone):\n", | |
" self.firstname = firstname\n", | |
" self.lastname = lastname\n", | |
" self._phone = phone\n", | |
" \n", | |
" @property\n", | |
" def fullname(self):\n", | |
" return \"{} {}\".format(self.firstname, self.lastname)\n", | |
"\n", | |
" @property\n", | |
" def phone(self):\n", | |
" return self._phone\n", | |
" \n", | |
" @phone.setter\n", | |
" def phone(self, value):\n", | |
" if not re.match(\"[0-9]+\", value):\n", | |
" raise ValueError(\"Invalid Phone number\")\n", | |
" self._phone = value\n", | |
" \n", | |
" # The same thing can also be done as:\n", | |
" def get_phone(self):\n", | |
" return self._phone\n", | |
" \n", | |
" def set_phone(self, value):\n", | |
" if not re.match(\"[0-9]+\", value):\n", | |
" raise ValueError(\"Invalid Phone number\")\n", | |
" self._phone = value\n", | |
" \n", | |
" phone2 = property(get_phone, set_phone)\n", | |
"\n", | |
"p = Person(\"Foo\", \"Bar\", \"1234\")\n", | |
"print p.phone\n", | |
"p.phone = \"bad-value\"\n", | |
"print p.phone" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"ename": "ValueError", | |
"evalue": "Invalid Phone number", | |
"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-65-f475fee4479a>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[1;32m 33\u001b[0m \u001b[0mp\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mPerson\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"Foo\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m\"Bar\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m\"1234\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 34\u001b[0m \u001b[0;32mprint\u001b[0m \u001b[0mp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mphone\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 35\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-value\"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 36\u001b[0m \u001b[0;32mprint\u001b[0m \u001b[0mp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mphone\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", | |
"\u001b[0;32m<ipython-input-65-f475fee4479a>\u001b[0m in \u001b[0;36mphone\u001b[0;34m(self, value)\u001b[0m\n\u001b[1;32m 17\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mphone\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mvalue\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 18\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0mre\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmatch\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"[0-9]+\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mvalue\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 19\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mValueError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"Invalid Phone number\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 20\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_phone\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mvalue\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 21\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", | |
"\u001b[0;31mValueError\u001b[0m: Invalid Phone number" | |
] | |
}, | |
{ | |
"output_type": "stream", | |
"stream": "stdout", | |
"text": [ | |
"1234\n" | |
] | |
} | |
], | |
"prompt_number": 65 | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"### new-style and old-style classes" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"class A:\n", | |
" pass\n", | |
"\n", | |
"class B(object):\n", | |
" pass\n", | |
"\n", | |
"a = A()\n", | |
"b = B()\n", | |
"\n", | |
"print type(a), type(b)" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"stream": "stdout", | |
"text": [ | |
"<type 'instance'> <class '__main__.B'>\n" | |
] | |
} | |
], | |
"prompt_number": 67 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"a + 1" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"ename": "TypeError", | |
"evalue": "unsupported operand type(s) for +: 'instance' and 'int'", | |
"output_type": "pyerr", | |
"traceback": [ | |
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m\n\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)", | |
"\u001b[0;32m<ipython-input-68-a1bd27f4633f>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0ma\u001b[0m \u001b[0;34m+\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", | |
"\u001b[0;31mTypeError\u001b[0m: unsupported operand type(s) for +: 'instance' and 'int'" | |
] | |
} | |
], | |
"prompt_number": 68 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"b + 1" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"ename": "TypeError", | |
"evalue": "unsupported operand type(s) for +: 'B' and 'int'", | |
"output_type": "pyerr", | |
"traceback": [ | |
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m\n\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)", | |
"\u001b[0;32m<ipython-input-69-60661c9df6ee>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mb\u001b[0m \u001b[0;34m+\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", | |
"\u001b[0;31mTypeError\u001b[0m: unsupported operand type(s) for +: 'B' and 'int'" | |
] | |
} | |
], | |
"prompt_number": 69 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"class A:\n", | |
" @property\n", | |
" def x(self):\n", | |
" return 1\n", | |
"\n", | |
"class B(object):\n", | |
" @property\n", | |
" def x(self):\n", | |
" return 1\n", | |
" \n", | |
"a = A()\n", | |
"b = B()\n", | |
"print a.x, b.x" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"stream": "stdout", | |
"text": [ | |
"1 1\n" | |
] | |
} | |
], | |
"prompt_number": 71 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"a.x = 2" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [], | |
"prompt_number": 72 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"print a.x" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"stream": "stdout", | |
"text": [ | |
"2\n" | |
] | |
} | |
], | |
"prompt_number": 73 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"b.x = 2" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"ename": "AttributeError", | |
"evalue": "can't set attribute", | |
"output_type": "pyerr", | |
"traceback": [ | |
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m\n\u001b[0;31mAttributeError\u001b[0m Traceback (most recent call last)", | |
"\u001b[0;32m<ipython-input-74-020d13f236c7>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mb\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mx\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;36m2\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", | |
"\u001b[0;31mAttributeError\u001b[0m: can't set attribute" | |
] | |
} | |
], | |
"prompt_number": 74 | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"**Descriptors**" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"class One(object):\n", | |
" def __get__(self, obj, type):\n", | |
" print \"__get__ called\", obj, One\n", | |
" if obj is None:\n", | |
" return self\n", | |
" return 1\n", | |
" \n", | |
" def __repr__(self):\n", | |
" return \"<one>\"\n", | |
" \n", | |
"class Foo(object):\n", | |
" x = One()\n", | |
" \n", | |
" @property\n", | |
" def y(self):\n", | |
" return 2\n", | |
" \n", | |
" def __repr__(self):\n", | |
" return \"Foo()\"\n", | |
" \n", | |
"f = Foo()\n", | |
"print f.x\n", | |
"print Foo.x" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"stream": "stdout", | |
"text": [ | |
"__get__ called Foo() <class '__main__.One'>\n", | |
"1\n", | |
"__get__ called None <class '__main__.One'>\n", | |
"<one>\n" | |
] | |
} | |
], | |
"prompt_number": 82 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"y = Foo.y\n", | |
"\n", | |
"print y.__get__(f, property)" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"stream": "stdout", | |
"text": [ | |
"2\n" | |
] | |
} | |
], | |
"prompt_number": 84 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"import re\n", | |
"re_email = re.compile(\".*@.*\")\n", | |
"\n", | |
"class Email(object):\n", | |
" \"\"\"Descriptor class to validate email addresses.\n", | |
" \"\"\"\n", | |
" def __init__(self):\n", | |
" self.value = None\n", | |
" \n", | |
" def __get__(self, obj, type):\n", | |
" if obj is None:\n", | |
" return self\n", | |
" return self.value\n", | |
" \n", | |
" def __set__(self, obj, value):\n", | |
" print \"__set__\", value\n", | |
" if re_email.match(value):\n", | |
" self.value = value\n", | |
" else:\n", | |
" raise ValueError(\"Invalid email\")\n", | |
" \n", | |
"class Person(object):\n", | |
" email = Email()\n", | |
" \n", | |
"p = Person()\n", | |
"print p.email\n", | |
"p.email = \"a@example.com\"\n", | |
"print p.email\n", | |
"p.email = \"bad-email\"\n" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"ename": "ValueError", | |
"evalue": "Invalid email", | |
"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-92-7b22aa81328e>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[1;32m 27\u001b[0m \u001b[0mp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0memail\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m\"a@example.com\"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 28\u001b[0m \u001b[0;32mprint\u001b[0m \u001b[0mp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0memail\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 29\u001b[0;31m \u001b[0mp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0memail\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m\"bad-email\"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", | |
"\u001b[0;32m<ipython-input-92-7b22aa81328e>\u001b[0m in \u001b[0;36m__set__\u001b[0;34m(self, obj, value)\u001b[0m\n\u001b[1;32m 18\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 19\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 20\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mValueError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"Invalid email\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 21\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 22\u001b[0m \u001b[0;32mclass\u001b[0m \u001b[0mPerson\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mobject\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", | |
"\u001b[0;31mValueError\u001b[0m: Invalid email" | |
] | |
}, | |
{ | |
"output_type": "stream", | |
"stream": "stdout", | |
"text": [ | |
"None\n", | |
"__set__ a@example.com\n", | |
"a@example.com\n", | |
"__set__ bad-email\n" | |
] | |
} | |
], | |
"prompt_number": 92 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"class my_property(object):\n", | |
" def __init__(self, func):\n", | |
" self.func = func\n", | |
" print \"my_property.__init__\", self.func\n", | |
" \n", | |
" def __get__(self, obj, type):\n", | |
" # convention used in descriptiors\n", | |
" # to return the descirptor when accessed \n", | |
" # from the class\n", | |
" if obj is None:\n", | |
" return self\n", | |
" return self.func(obj)\n", | |
"\n", | |
"class Foo(object):\n", | |
" #@my_property\n", | |
" def x(self):\n", | |
" print \"Foo.x function called\"\n", | |
" return 1\n", | |
" \n", | |
" x = my_property(x)\n", | |
" \n", | |
"f = Foo()\n", | |
"print f.x \n", | |
"print f.x " | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"stream": "stdout", | |
"text": [ | |
"my_property.__init__ <function x at 0x102ca2578>\n", | |
"Foo.x function called\n", | |
"1\n", | |
"Foo.x function called\n", | |
"1\n" | |
] | |
} | |
], | |
"prompt_number": 99 | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"**Problem** Write a descriptor `cached_property` that works like the property descriptor, but caches the result after calling the function once." | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"**Callable objects**" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"def square(x):\n", | |
" return x*x" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [], | |
"prompt_number": 100 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"square.__call__(3)" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"metadata": {}, | |
"output_type": "pyout", | |
"prompt_number": 101, | |
"text": [ | |
"9" | |
] | |
} | |
], | |
"prompt_number": 101 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"class Square:\n", | |
" def __call__(self, x):\n", | |
" return x*x\n", | |
" \n", | |
"sq = Square()\n", | |
"print sq(4)" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"stream": "stdout", | |
"text": [ | |
"16\n" | |
] | |
} | |
], | |
"prompt_number": 102 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"def make_adder(x):\n", | |
" def adder(y):\n", | |
" return x+y\n", | |
" return adder\n", | |
"\n", | |
"add5 = make_adder(5)\n", | |
"print add5(3)" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"stream": "stdout", | |
"text": [ | |
"8\n" | |
] | |
} | |
], | |
"prompt_number": 103 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"class Adder(object):\n", | |
" def __init__(self, x):\n", | |
" self.x = x\n", | |
" def __call__(self, y):\n", | |
" return self.x + y\n", | |
" \n", | |
"add5 = Adder(5)\n", | |
"print add5(3)\n", | |
"print add5.x\n", | |
"add5.x = 2\n", | |
"print add5(7)" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"stream": "stdout", | |
"text": [ | |
"8\n", | |
"5\n", | |
"9\n" | |
] | |
} | |
], | |
"prompt_number": 111 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"Adder.__call__" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"metadata": {}, | |
"output_type": "pyout", | |
"prompt_number": 107, | |
"text": [ | |
"<unbound method Adder.__call__>" | |
] | |
} | |
], | |
"prompt_number": 107 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"Adder.__class__" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"metadata": {}, | |
"output_type": "pyout", | |
"prompt_number": 108, | |
"text": [ | |
"type" | |
] | |
} | |
], | |
"prompt_number": 108 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"type.__call__(Adder, 5)" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"metadata": {}, | |
"output_type": "pyout", | |
"prompt_number": 109, | |
"text": [ | |
"<__main__.Adder at 0x102ca3f10>" | |
] | |
} | |
], | |
"prompt_number": 109 | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"Memoize as a class." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"class memoize:\n", | |
" def __init__(self, func):\n", | |
" self.func = func\n", | |
" self.cache = {}\n", | |
" \n", | |
" def reset_cache(self):\n", | |
" self.cache.clear()\n", | |
" \n", | |
" def __call__(self, *args):\n", | |
" if args not in self.cache:\n", | |
" self.cache[args] = self.func(*args)\n", | |
" return self.cache[args]\n", | |
" \n", | |
"@memoize\n", | |
"def square(n):\n", | |
" print \"square\", n\n", | |
" return n*n\n", | |
" \n", | |
"print square(2)\n", | |
"print square(2)\n", | |
"print square(2)\n", | |
"square.reset_cache()\n", | |
"print square(2)\n", | |
"print square(2)\n", | |
"print square(2)\n" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"stream": "stdout", | |
"text": [ | |
"square 2\n", | |
"4\n", | |
"4\n", | |
"4\n", | |
"square 2\n", | |
"4\n", | |
"4\n", | |
"4\n" | |
] | |
} | |
], | |
"prompt_number": 114 | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"**Meta classes**" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"x = 1\n", | |
"print type(x)" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"stream": "stdout", | |
"text": [ | |
"<type 'int'>\n" | |
] | |
} | |
], | |
"prompt_number": 116 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"print type(int)" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"stream": "stdout", | |
"text": [ | |
"<type 'type'>\n" | |
] | |
} | |
], | |
"prompt_number": 117 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"print type(type)" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"stream": "stdout", | |
"text": [ | |
"<type 'type'>\n" | |
] | |
} | |
], | |
"prompt_number": 119 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"Point = type(\"Point\", (object,), {\"x\": 0, \"y\": 0})" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [], | |
"prompt_number": 120 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"Point" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"metadata": {}, | |
"output_type": "pyout", | |
"prompt_number": 121, | |
"text": [ | |
"__main__.Point" | |
] | |
} | |
], | |
"prompt_number": 121 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"Point.x" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"metadata": {}, | |
"output_type": "pyout", | |
"prompt_number": 122, | |
"text": [ | |
"0" | |
] | |
} | |
], | |
"prompt_number": 122 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"p = Point()" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [], | |
"prompt_number": 123 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"class Point(object):\n", | |
" x = 0\n", | |
" y = 0" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [], | |
"prompt_number": 124 | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"The above snippet is eqvivalant to " | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"Point = type(\"Point\", (object,), {\"x\": 0, \"y\": 0})" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [], | |
"prompt_number": 125 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"A = type(\"A\", (object,), {\"x\": 0})\n", | |
"B = type(\"B\", (A,), {\"y\": 1})" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [], | |
"prompt_number": 127 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"B" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"metadata": {}, | |
"output_type": "pyout", | |
"prompt_number": 128, | |
"text": [ | |
"__main__.B" | |
] | |
} | |
], | |
"prompt_number": 128 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"B.x" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"metadata": {}, | |
"output_type": "pyout", | |
"prompt_number": 129, | |
"text": [ | |
"0" | |
] | |
} | |
], | |
"prompt_number": 129 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"B.y" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"metadata": {}, | |
"output_type": "pyout", | |
"prompt_number": 130, | |
"text": [ | |
"1" | |
] | |
} | |
], | |
"prompt_number": 130 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"B.__bases__" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"metadata": {}, | |
"output_type": "pyout", | |
"prompt_number": 131, | |
"text": [ | |
"(__main__.A,)" | |
] | |
} | |
], | |
"prompt_number": 131 | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"Since type is a class, it should be possible to subclass it." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"class type2(type):\n", | |
" pass" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [], | |
"prompt_number": 132 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"A = type2(\"A\", (), {})" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [], | |
"prompt_number": 133 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"A" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"metadata": {}, | |
"output_type": "pyout", | |
"prompt_number": 134, | |
"text": [ | |
"__main__.A" | |
] | |
} | |
], | |
"prompt_number": 134 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"a = A()" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [], | |
"prompt_number": 135 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"print type(a)" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"stream": "stdout", | |
"text": [ | |
"<class '__main__.A'>\n" | |
] | |
} | |
], | |
"prompt_number": 136 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"print type(A)" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"stream": "stdout", | |
"text": [ | |
"<class '__main__.type2'>\n" | |
] | |
} | |
], | |
"prompt_number": 137 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"class type2(type):\n", | |
" def __init__(self, name, bases, attrs):\n", | |
" print \"type2.__init__\", name, bases, attrs\n", | |
" type.__init__(self, name, bases, attrs)" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [], | |
"prompt_number": 138 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"A = type2(\"A\", (), {})" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"stream": "stdout", | |
"text": [ | |
"type2.__init__ A () {}\n" | |
] | |
} | |
], | |
"prompt_number": 139 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"class B(A):\n", | |
" pass" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"stream": "stdout", | |
"text": [ | |
"type2.__init__ B (<class '__main__.A'>,) {'__module__': '__main__'}\n" | |
] | |
} | |
], | |
"prompt_number": 140 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"class A(object):\n", | |
" __metaclass__ = type2" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"stream": "stdout", | |
"text": [ | |
"type2.__init__ A (<type 'object'>,) {'__module__': '__main__', '__metaclass__': <class '__main__.type2'>}\n" | |
] | |
} | |
], | |
"prompt_number": 141 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"class B(A): pass" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"stream": "stdout", | |
"text": [ | |
"type2.__init__ B (<class '__main__.A'>,) {'__module__': '__main__'}\n" | |
] | |
} | |
], | |
"prompt_number": 142 | |
}, | |
{ | |
"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