Skip to content

Instantly share code, notes, and snippets.

@anandology anandology/day1.ipynb
Last active Aug 29, 2015

Embed
What would you like to do?
Advanced Python Training at LinkedIn -- Feb 26 - Mar 1, 2014
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
{
"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
You can’t perform that action at this time.