Skip to content

Instantly share code, notes, and snippets.

@anandology
Last active December 28, 2015 06:59
Show Gist options
  • Save anandology/7460837 to your computer and use it in GitHub Desktop.
Save anandology/7460837 to your computer and use it in GitHub Desktop.
Advanced Python Workshop - Nov 2013 http://advancedpython.hasgeek.com/
Notes from Advanced Python Workshop by Anand Chitipothu conducted on Nov 14-16, 2013
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": ""
},
"nbformat": 3,
"nbformat_minor": 0,
"worksheets": [
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Advanced Python Workshop - Day 3\n",
"Nov 16, 2013<br/>\n",
"http://advancedpython.hasgeek.com/"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"x = 1"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 2
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"print type(x)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"<type 'int'>\n"
]
}
],
"prompt_number": 4
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"int.__bases__"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 5,
"text": [
"(object,)"
]
}
],
"prompt_number": 5
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"print type(int)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"<type 'type'>\n"
]
}
],
"prompt_number": 6
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"print type(type)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"<type 'type'>\n"
]
}
],
"prompt_number": 7
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"type.__bases__"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 8,
"text": [
"(object,)"
]
}
],
"prompt_number": 8
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"print type(object)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"<type 'type'>\n"
]
}
],
"prompt_number": 9
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"object.__bases__"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 10,
"text": [
"()"
]
}
],
"prompt_number": 10
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"class Point(object):\n",
" x = 0\n",
" y = 0"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 11
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"print Point"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"<class '__main__.Point'>\n"
]
}
],
"prompt_number": 12
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"type(Point)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 13,
"text": [
"type"
]
}
],
"prompt_number": 13
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"isinstance(Point, type)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 14,
"text": [
"True"
]
}
],
"prompt_number": 14
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"p = Point()"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 15
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Just like we can create an instance of Point class, we can also create an instance of type. In fact the class statement is a syntactic-sugar of creating an instance of type."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"Point2 = type(\"Point2\", (object,), {\"x\": 0, \"y\": 0})"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 16
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"Point2"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 17,
"text": [
"__main__.Point2"
]
}
],
"prompt_number": 17
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"Point"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 18,
"text": [
"__main__.Point"
]
}
],
"prompt_number": 18
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"Point.x"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 19,
"text": [
"0"
]
}
],
"prompt_number": 19
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"Point2.x"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 21,
"text": [
"0"
]
}
],
"prompt_number": 21
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"Point.__dict__"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 22,
"text": [
"<dictproxy {'__dict__': <attribute '__dict__' of 'Point' objects>,\n",
" '__doc__': None,\n",
" '__module__': '__main__',\n",
" '__weakref__': <attribute '__weakref__' of 'Point' objects>,\n",
" 'x': 0,\n",
" 'y': 0}>"
]
}
],
"prompt_number": 22
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"Point2.__dict__"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 23,
"text": [
"<dictproxy {'__dict__': <attribute '__dict__' of 'Point2' objects>,\n",
" '__doc__': None,\n",
" '__module__': '__main__',\n",
" '__weakref__': <attribute '__weakref__' of 'Point2' objects>,\n",
" 'x': 0,\n",
" 'y': 0}>"
]
}
],
"prompt_number": 23
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"class type2(type):\n",
" pass"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 24
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"Point3 = type2(\"Point3\", (object,), {\"x\":0, \"y\": 0})"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 25
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"Point3"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 26,
"text": [
"__main__.Point3"
]
}
],
"prompt_number": 26
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"type(Point3)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 27,
"text": [
"__main__.type2"
]
}
],
"prompt_number": 27
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"Point3.__class__"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 28,
"text": [
"__main__.type2"
]
}
],
"prompt_number": 28
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"class type3(type):\n",
" xxx = 1234"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 29
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"Point3 = type3(\"Point3\", (object,), {})"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 30
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"Point3.xxx"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 31,
"text": [
"1234"
]
}
],
"prompt_number": 31
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"type(type3)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 32,
"text": [
"type"
]
}
],
"prompt_number": 32
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"How can we create an instance of type3 using the class statement?"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"class Point3a(object):\n",
" pass\n",
"\n",
"print type(Point3a)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"<type 'type'>\n"
]
}
],
"prompt_number": 34
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"class Point3b(object):\n",
" __metaclass__ = type2\n",
" pass\n",
"\n",
"print type(Point3b)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"<class '__main__.type2'>\n"
]
}
],
"prompt_number": 35
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This is same as\n",
"\n",
"<pre>\n",
"Point3b = type2(\"Point3b\", (object,), {})\n",
"</pre>"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The metaclass is retained in all sub classes as well."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"class Foo(Point3b): pass\n",
"\n",
"print type(Foo)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"<class '__main__.type2'>\n"
]
}
],
"prompt_number": 36
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"class LoggingMetaClass(type):\n",
" def __init__(self, *a, **kw):\n",
" type.__init__(self, *a, **kw)\n",
" print self, \"defined now\"\n",
"\n",
"print \"before Node class\" \n",
"class Node(object):\n",
" __metaclass__ = LoggingMetaClass\n",
"print \"after Node class\" \n",
" \n",
"class Div(Node): pass \n",
"class Pre(Node): pass \n",
"class H1(Node): pass \n",
"class H2(Node): pass \n",
" "
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"before Node class\n",
"<class '__main__.Node'> defined now\n",
"after Node class\n",
"<class '__main__.Div'> defined now\n",
"<class '__main__.Pre'> defined now\n",
"<class '__main__.H1'> defined now\n",
"<class '__main__.H2'> defined now\n"
]
}
],
"prompt_number": 39
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Example: web framework**"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Can we have an API which looks like this:\n",
"\n",
" class hello(page):\n",
" def GET(self):\n",
" print \"hello\"\n",
" \n",
" class goodbye(page):\n",
" def GET(self):\n",
" print \"goodbye\"\n",
" \n",
" if __name__ == \"__main__\": \n",
" request(\"/hello\")\n",
" request(\"/goodbye\") \n",
" request(\"/no-such-page\") \n",
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Can we use a metaclass to create path to class registry?"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%%file meta_web.py\n",
"\n",
"path_mapping = []\n",
"\n",
"class MetaPage(type):\n",
" def __init__(self, *a, **kw):\n",
" type.__init__(self, *a, **kw)\n",
" path = \"/\" + self.__name__\n",
" path_mapping.append((path, self))\n",
" print \"added\", path, \"to mapping\"\n",
"\n",
"class page(object):\n",
" __metaclass__ = MetaPage\n",
"\n",
"def request(path):\n",
" for p, cls in path_mapping:\n",
" if p == path:\n",
" return cls().GET()\n",
" print \"404 Not Found\"\n"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"Overwriting meta_web.py\n"
]
}
],
"prompt_number": 44
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%%file meta_app1.py\n",
"from meta_web import page, request\n",
"\n",
"class hello(page):\n",
" def GET(self):\n",
" print \"hello\"\n",
" \n",
"class goodbye(page):\n",
" def GET(self):\n",
" print \"goodbye\"\n",
" \n",
"if __name__ == \"__main__\": \n",
" request(\"/hello\")\n",
" request(\"/goodbye\") \n",
" request(\"/no-such-page\") \n",
" "
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"Overwriting meta_app1.py\n"
]
}
],
"prompt_number": 45
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"!python meta_app1.py"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"added /page to mapping\r\n",
"added /hello to mapping\r\n",
"added /goodbye to mapping\r\n",
"hello\r\n",
"goodbye\r\n",
"404 Not Found\r\n"
]
}
],
"prompt_number": 46
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Problem:** Improve the framework to use the path specified in the `path` attribute of the class instead of the class name. If the path attribute is not specified, it should infer the path from the class name.\n",
"\n",
" class index(page):\n",
" path = \"/\"\n",
" def GET(self):\n",
" print \"Home Page\"\n",
" \n",
" class login(page):\n",
" path = \"/account/login\"\n",
" def GET(self):\n",
" print \"Login Form\""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"How does `class Meta` in dango works? \n",
"\n",
"That is nothing to do with metaclasses.\n",
"\n",
"Lets try to change the above problem to use a class Meta.\n",
"\n",
" class index(page):\n",
" class Meta:\n",
" path = \"/\"\n",
" log_level = \"DEBUG\"\n",
" \n",
" def GET(self):\n",
" print \"Home Page\"\n",
"\n",
"The `class Meta` is just used as a namespace to hold bunch of atrributes together. The name `Meta` is what the library/framework expects.\n",
"\n",
"Putting it in another way:\n",
"\n",
" class index(page): \n",
" Meta = type(\"Meta\", (object,), {\"path\": \"/\", \"log_level\": \"DEBUG\"})\n",
" \n",
" def GET(self):\n",
" print \"Home Page\"\n",
"\n",
"How to access `Meta`?\n",
"\n",
" m = index.Meta()\n",
"\n",
"It is just like accessing a class attribute `Point.x`.\n",
"\n",
"\n",
"It would give same effect as using a dict, but writing a class looks simpler.\n",
"\n",
" class index(page): \n",
" meta = {\"path\": \"/\", \"log_level\": \"DEBUG\"}\n",
" \n",
"is probably more verbose than writing a class.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Example: final class a.la. java"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"class FinalMeta(type):\n",
" def __init__(self, name, bases, attrs):\n",
" # raise error if the class is begin extended from a final class, \n",
" if any(isinstance(b, FinalMeta) for b in bases):\n",
" raise Exception(\"You can't extend from a final class.\")\n",
" type.__init__(self, name, bases, attrs)\n",
" print \"created class\", self\n",
" \n",
"class FinalFoo(object):\n",
" __metaclass__ = FinalMeta\n",
" \n",
"class FinalBar(FinalFoo):\n",
" pass\n",
" "
],
"language": "python",
"metadata": {},
"outputs": [
{
"ename": "Exception",
"evalue": "You can't extend from a final class.",
"output_type": "pyerr",
"traceback": [
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m\n\u001b[0;31mException\u001b[0m Traceback (most recent call last)",
"\u001b[0;32m<ipython-input-55-7dc13b888a25>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[1;32m 10\u001b[0m \u001b[0m__metaclass__\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mFinalMeta\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 11\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 12\u001b[0;31m \u001b[0;32mclass\u001b[0m \u001b[0mFinalBar\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mFinalFoo\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 13\u001b[0m \u001b[0;32mpass\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 14\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;32m<ipython-input-55-7dc13b888a25>\u001b[0m in \u001b[0;36m__init__\u001b[0;34m(self, name, bases, attrs)\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0;31m# raise error if the class is begin extended from a final class,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0many\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0misinstance\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mb\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mFinalMeta\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mb\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mbases\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 5\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mException\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"You can't extend from a final class.\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 6\u001b[0m \u001b[0mtype\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m__init__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mname\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mbases\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mattrs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 7\u001b[0m \u001b[0;32mprint\u001b[0m \u001b[0;34m\"created class\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;31mException\u001b[0m: You can't extend from a final class."
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"created class <class '__main__.FinalFoo'>\n"
]
}
],
"prompt_number": 55
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## `__new__` "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The `__init__` method is called to initialize the object after it is created. The `__new__` method is called to create the object itself."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"class Point(object):\n",
" def __new__(cls, *a, **kw):\n",
" print \"Point.__new__\", cls, a, kw \n",
" return object.__new__(cls, *a, **kw)\n",
"\n",
" def __init__(*a, **kw):\n",
" print \"Point.__init__\", a, kw \n",
"\n",
"p = Point(1, 2)\n",
"print p"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"Point.__new__ <class '__main__.Point'> (1, 2) {}\n",
"Point.__init__ (<__main__.Point object at 0x101993f50>, 1, 2) {}\n",
"<__main__.Point object at 0x101993f50>\n"
]
}
],
"prompt_number": 66
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Example: Singleton**"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"class Singleton(object):\n",
" def __new__(cls, *a, **kw):\n",
" try:\n",
" i = cls.INSTANCE\n",
" print \"reusing old instance of\", cls\n",
" return i\n",
" except AttributeError:\n",
" print \"creating new instance of\", cls\n",
" cls.INSTANCE = object.__new__(cls, *a, **kw)\n",
" return cls.INSTANCE\n",
"\n",
"class Zero(Singleton):\n",
" pass\n",
"\n",
"z0 = Zero()\n",
"z1 = Zero()\n",
"\n",
"print id(z0), id(z1)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"creating new instance of <class '__main__.Zero'>\n",
"reusing old instance of <class '__main__.Zero'>\n",
"4321867472 4321867472\n"
]
}
],
"prompt_number": 73
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Problem** Write a class Cached, which memoizes class creation and reuses existing objects when called with same arguments.\n",
"\n",
" class Point(Cached):\n",
" def __init__(self, x, y):\n",
" self.x = x\n",
" self.y = y\n",
" \n",
" \n",
" p1 = Point(1, 2)\n",
" p2 = Point(1, 2)\n",
" print p1 is p2 # True"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Possible solution:\n",
"\n",
" class Cached(object):\n",
" @memoize\n",
" def __new__(cls, *a):\n",
" return object.__new__(cls, *a)\n",
" \n",
" class Point(Cached):\n",
" def __init__(self, x, y):\n",
" self.x = x\n",
" self.y = y\n",
" \n",
" \n",
" p1 = Point(1, 2)\n",
" p2 = Point(1, 2)\n",
" print p1 is p2 # True \n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**staticmethod and classmethod**"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"import json\n",
"\n",
"class Point:\n",
" def __init__(self, x, y):\n",
" self.x = x\n",
" self.y = y\n",
" \n",
" def to_dict(self):\n",
" return {\"x\": self.x, \"y\": self.y}\n",
" \n",
" def to_json(self):\n",
" return json.dumps(self.to_dict())\n",
"\n",
"p1 = Point(1, 2)\n",
"print p1.to_json()"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"{\"y\": 2, \"x\": 1}\n"
]
}
],
"prompt_number": 74
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"What about `from_json`?"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"import json\n",
"\n",
"class Point(object):\n",
" def __init__(self, x, y):\n",
" self.x = x\n",
" self.y = y\n",
" \n",
" def __repr__(self):\n",
" return \"Point(%d, %d)\" % (self.x, self.y)\n",
" \n",
" def to_dict(self):\n",
" return {\"x\": self.x, \"y\": self.y}\n",
" \n",
" def to_json(self):\n",
" return json.dumps(self.to_dict())\n",
" \n",
" @staticmethod\n",
" def from_json(jsontext):\n",
" d = json.loads(jsontext)\n",
" return Point(d['x'], d['y'])\n",
"\n",
"p1 = Point(1, 2)\n",
"print p1\n",
"jsontext = p1.to_json()\n",
"\n",
"# create point from jsontext\n",
"p2 = Point.from_json(jsontext)\n",
"print p2"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"Point(1, 2)\n",
"Point(1, 2)\n"
]
}
],
"prompt_number": 78
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Why can't I put it outside the class?\n",
"\n",
"What if you have multiple classes?"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"class Size(object):\n",
" a = 1\n",
" def __init__(self, w, h):\n",
" self.w = w\n",
" self.h = h\n",
"\n",
" def __repr__(self):\n",
" return \"Size(%d, %d)\" % (self.w, self.h)\n",
" \n",
" def to_json(self):\n",
" return json.dumps({\"w\": self.w, \"h\": self.h})\n",
" \n",
" @staticmethod\n",
" def from_json(jsontext):\n",
" d = json.loads(jsontext)\n",
" return Size(d['w'], d['h'])\n",
" \n",
"\n",
"s1 = Size(10, 20)\n",
"text = s1.to_json()\n",
"s2 = Size.from_json(text)\n",
"print s1, s2"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"Size(10, 20) Size(10, 20)\n"
]
}
],
"prompt_number": 79
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The code for both Point and Size look almost the same. Can we generalize that?"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%%file fromjson.py\n",
"from __future__ import unicode_literals\n",
"import json\n",
"\n",
"class Serializable(object):\n",
" @classmethod\n",
" def from_json(cls, jsontext):\n",
" d = json.loads(jsontext)\n",
" return cls.from_dict(d)\n",
" \n",
" @classmethod\n",
" def from_dict(cls, d):\n",
" return cls(**d)\n",
" \n",
" def to_json(self):\n",
" return json.dumps(self.to_dict())\n",
" \n",
" def to_dict(self):\n",
" return self.__dict__\n",
" \n",
" \n",
"class Point(Serializable):\n",
" def __init__(self, x, y):\n",
" self.x = x\n",
" self.y = y\n",
" \n",
" def __repr__(self):\n",
" return \"Point(%d, %d)\" % (self.x, self.y)\n",
" \n",
"class Size(Serializable):\n",
" def __init__(self, w, h):\n",
" self.w = w\n",
" self.h = h\n",
" \n",
" def __repr__(self):\n",
" return \"Size(%d, %d)\" % (self.w, self.h)\n",
" \n",
"\n",
"p1 = Point(1, 2)\n",
"print p1\n",
"\n",
"p2 = Point.from_json(p1.to_json())\n",
"print p2\n",
"\n",
"s1 = Size(1, 2)\n",
"print s1\n",
"s2 = Size.from_json(s1.to_json())\n",
"print s2"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"Overwriting fromjson.py\n"
]
}
],
"prompt_number": 91
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"!python2.7 fromjson.py"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"Point(1, 2)\r\n",
"Point(1, 2)\r\n",
"Size(1, 2)\r\n",
"Size(1, 2)\r\n"
]
}
],
"prompt_number": 92
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**property**"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"import re\n",
"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",
" print \"get_phone\"\n",
" return self._phone\n",
" \n",
" @phone.setter\n",
" def phone(self, phone):\n",
" print \"set_phone\", phone\n",
" if not re.match(\"^[0-9 ]+$\", phone):\n",
" raise ValueError(\"Bad phone number: %r\" % phone)\n",
" self._phone = phone\n",
" \n",
" #phone = property(get_phone, set_phone)\n",
" \n",
" def __repr__(self):\n",
" return \"Person(%s, %s)\" % (self.fullname, self._phone)\n",
" \n",
"\n",
"p1 = Person(\"Joe\", \"12345567\")\n",
"print p1\n",
"\n",
"p1.phone = \"bad number\"\n",
"print p1"
],
"language": "python",
"metadata": {},
"outputs": [
{
"ename": "ValueError",
"evalue": "Bad phone number: u'bad 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-112-4d63f40fcd67>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[1;32m 26\u001b[0m \u001b[0;32mprint\u001b[0m \u001b[0mp1\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 27\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 28\u001b[0;31m \u001b[0mp1\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mphone\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m\"bad number\"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 29\u001b[0m \u001b[0;32mprint\u001b[0m \u001b[0mp1\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;32m<ipython-input-112-4d63f40fcd67>\u001b[0m in \u001b[0;36mphone\u001b[0;34m(self, phone)\u001b[0m\n\u001b[1;32m 14\u001b[0m \u001b[0;32mprint\u001b[0m \u001b[0;34m\"set_phone\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mphone\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 15\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[0mphone\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 16\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mValueError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"Bad phone number: %r\"\u001b[0m \u001b[0;34m%\u001b[0m \u001b[0mphone\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 17\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_phone\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mphone\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 18\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;31mValueError\u001b[0m: Bad phone number: u'bad number'"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"Person(Joe, 12345567)\n",
"set_phone bad number\n"
]
}
],
"prompt_number": 112
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Problem** Create a `slug` proprty for this following class.\n",
"\n",
" class Post(object):\n",
" def __init__(self, date, title):\n",
" self.date = date\n",
" self.title = title\n",
" \n",
"The date will be an instance of `datetime.date` class and title will be a string. The URL will be in the form of `\"/2013/09/11/title-comes-here\"`\n",
"\n",
"\n",
" from datetime import date\n",
" p = Post(date(2013, 9, 11), \"Hello world\")\n",
" print p.slug"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**old-style and new-style classes**"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"class A:\n",
" pass\n",
"a = A()\n",
"print type(a)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"<type 'instance'>\n"
]
}
],
"prompt_number": 113
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"type(A)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 114,
"text": [
"classobj"
]
}
],
"prompt_number": 114
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"class B(object):\n",
" pass\n",
"b = B()\n",
"print type(b)\n",
"print type(B)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"<class '__main__.B'>\n",
"<type 'type'>\n"
]
}
],
"prompt_number": 115
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"len(a)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"ename": "AttributeError",
"evalue": "A instance has no attribute '__len__'",
"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-116-af8c77e09569>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mlen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
"\u001b[0;31mAttributeError\u001b[0m: A instance has no attribute '__len__'"
]
}
],
"prompt_number": 116
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"a.__len__ = lambda: 0\n",
"b.__len__ = lambda: 0"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 117
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"len(a)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 118,
"text": [
"0"
]
}
],
"prompt_number": 118
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"len(b)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"ename": "TypeError",
"evalue": "object of type 'B' has no len()",
"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-119-f311c9fb5505>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mlen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mb\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
"\u001b[0;31mTypeError\u001b[0m: object of type 'B' has no len()"
]
}
],
"prompt_number": 119
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"new-style class looks for `__xxx__` methods in the class where as old-style lcass looks for it in the object."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Descriptors"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"class A(object):\n",
" @property\n",
" def x(self):\n",
" return 0\n",
" \n",
"a = A()\n",
"A.__dict__"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 125,
"text": [
"<dictproxy {'__dict__': <attribute '__dict__' of 'A' objects>,\n",
" '__doc__': None,\n",
" '__module__': '__main__',\n",
" '__weakref__': <attribute '__weakref__' of 'A' objects>,\n",
" 'x': <property at 0x1019c5158>}>"
]
}
],
"prompt_number": 125
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"A.x"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 126,
"text": [
"<property at 0x1019c5158>"
]
}
],
"prompt_number": 126
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"dir(A.x)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 127,
"text": [
"['__class__',\n",
" '__delattr__',\n",
" '__delete__',\n",
" '__doc__',\n",
" '__format__',\n",
" '__get__',\n",
" '__getattribute__',\n",
" '__hash__',\n",
" '__init__',\n",
" '__new__',\n",
" '__reduce__',\n",
" '__reduce_ex__',\n",
" '__repr__',\n",
" '__set__',\n",
" '__setattr__',\n",
" '__sizeof__',\n",
" '__str__',\n",
" '__subclasshook__',\n",
" 'deleter',\n",
" 'fdel',\n",
" 'fget',\n",
" 'fset',\n",
" 'getter',\n",
" 'setter']"
]
}
],
"prompt_number": 127
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"A.x.__get__(a)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 130,
"text": [
"0"
]
}
],
"prompt_number": 130
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"class Zero(object):\n",
" def __get__(self, obj, type=None):\n",
" print \"Zero.__get__\", obj, type\n",
" return 0\n",
" \n",
" def __set__(self, obj, value):\n",
" print \"__set__\"\n",
" raise AttributeError()\n",
" \n",
" def __repr__(self):\n",
" return \"<Zero>\"\n",
"\n",
"class A(object):\n",
" x = Zero()\n",
" \n",
"a = A()\n",
"print a.x"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"Zero.__get__ <__main__.A object at 0x101996e10> <class '__main__.A'>\n",
"0\n"
]
}
],
"prompt_number": 151
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Lets try to implement property decorator ourselves."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"class my_property(object):\n",
" def __init__(self, getter, setter=None):\n",
" print \"my_property.__init__\", getter\n",
" self._getter = getter\n",
" self._setter = setter\n",
" \n",
" def setter(self, func):\n",
" self._setter = func\n",
" return self\n",
" \n",
" def __get__(self, obj, type=None):\n",
" print \"my_property.__get__\", obj\n",
" return self._getter(obj)\n",
" \n",
" def __set__(self, obj, value):\n",
" print \"my_property.__set__\", obj, value\n",
" if self._setter is None:\n",
" raise AttributeError\n",
" else:\n",
" return self._setter(obj, value)\n",
"\n",
"class A(object):\n",
" def __init__(self):\n",
" self._x = 0\n",
" \n",
" @my_property\n",
" def x(self):\n",
" print \"A.x\"\n",
" return self._x\n",
" \n",
" @x.setter\n",
" def x(self, value):\n",
" print \"A.x setter\"\n",
" self._x = value\n",
" \n",
"print \"end of class\" \n",
"a = A()\n",
"print a.x\n",
"a.x = 1"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"my_property.__init__ <function x at 0x10198fc08>\n",
"end of class\n",
"my_property.__get__ <__main__.A object at 0x101b22950>\n",
"A.x\n",
"0\n",
"my_property.__set__ <__main__.A object at 0x101b22950> 1\n",
"A.x setter\n"
]
}
],
"prompt_number": 168
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Problem** Implement a descriptor Constant, which doesn't allow changing the value.\n",
"\n",
" class Circle:\n",
" pi = Constant(3.14)\n",
" \n",
" c = Circle()\n",
" print c.pi\n",
" \n",
" c.pi = 3.0 # error"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We can use descriptors for doing various validations."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"class BaseField(object):\n",
" def __init__(self):\n",
" self.value = None\n",
" \n",
" def __get__(self, obj, type):\n",
" return self.value\n",
" \n",
" def __set__(self, obj, value):\n",
" self.value = self.parse(obj, value)\n",
" \n",
" def parse(self, obj, value):\n",
" return value \n",
" \n",
"class IntegerField(BaseField):\n",
" def parse(self, obj, value):\n",
" return int(value)\n",
" \n",
"class Point(object):\n",
" x = IntegerField()\n",
" y = IntegerField()\n",
" \n",
"p = Point()\n",
"p.x = 1\n",
"p.y = 34\n",
"print p.x, p.y\n",
"\n",
"p.x = \"foo\""
],
"language": "python",
"metadata": {},
"outputs": [
{
"ename": "ValueError",
"evalue": "invalid literal for int() with base 10: 'foo'",
"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-172-57a9c35436e1>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[1;32m 25\u001b[0m \u001b[0;32mprint\u001b[0m \u001b[0mp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0my\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 26\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 27\u001b[0;31m \u001b[0mp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mx\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m\"foo\"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
"\u001b[0;32m<ipython-input-172-57a9c35436e1>\u001b[0m in \u001b[0;36m__set__\u001b[0;34m(self, obj, value)\u001b[0m\n\u001b[1;32m 7\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 8\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0m__set__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mobj\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----> 9\u001b[0;31m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mvalue\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mparse\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mobj\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 10\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 11\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mparse\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mobj\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<ipython-input-172-57a9c35436e1>\u001b[0m in \u001b[0;36mparse\u001b[0;34m(self, obj, value)\u001b[0m\n\u001b[1;32m 14\u001b[0m \u001b[0;32mclass\u001b[0m \u001b[0mIntegerField\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mBaseField\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 15\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mparse\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mobj\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---> 16\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mint\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 17\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 18\u001b[0m \u001b[0;32mclass\u001b[0m \u001b[0mPoint\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 literal for int() with base 10: 'foo'"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"1 34\n"
]
}
],
"prompt_number": 172
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Context Managers"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"with open(\"numbers.txt\") as f:\n",
" f.read()"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 174
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The with statement takes care of closing the file."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"f = open(\"numbers.txt\")"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 176
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"f.__enter__"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 177,
"text": [
"<function __enter__>"
]
}
],
"prompt_number": 177
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"f.__exit__"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 178,
"text": [
"<function __exit__>"
]
}
],
"prompt_number": 178
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Example: chdir**"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Lets try to implement a context manager to change directory for a block of code.\n",
"\n",
" print os.getcwd()\n",
" with chdir(\"/tmp\"):\n",
" print os.getcwd()\n",
" print os.getcwd() "
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"import os\n",
"\n",
"class chdir(object):\n",
" def __init__(self, path):\n",
" self.path = path\n",
" \n",
" def __enter__(self):\n",
" self.old_cwd = os.getcwd()\n",
" os.chdir(self.path)\n",
" return self\n",
" \n",
" def __exit__(self, *a):\n",
" os.chdir(self.old_cwd)\n",
" \n",
"\n",
"print os.getcwd()\n",
"with chdir(\"/tmp\"):\n",
" print os.getcwd()\n",
" print os.popen(\"pwd\").read()\n",
"print os.getcwd()"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"/Users/anand/Dropbox/Trainings/2013/advancedpython-nov2013/notes\n",
"/private/tmp\n",
"/private/tmp\n",
"\n",
"/Users/anand/Dropbox/Trainings/2013/advancedpython-nov2013/notes\n"
]
}
],
"prompt_number": 182
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Lets see what happens on exceptions."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"class foo(object):\n",
" def __enter__(self):\n",
" print \"__enter__\"\n",
" return 1\n",
" \n",
" def __exit__(self, type, exc, traceback):\n",
" print \"__exit__\", type, exc, traceback\n",
" # If __exit__ returns True, the exception is supressed\n",
" return True\n",
"\n",
"with foo() as x:\n",
" print x\n",
" raise Exception(\"with in with\")"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"__enter__\n",
"1\n",
"__exit__ <type 'exceptions.Exception'> with in with <traceback object at 0x101b37710>\n"
]
}
],
"prompt_number": 188
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Problem** Write a context manager `ignore_exception` to ignore any exception raised in the with block.\n",
"\n",
" with ignore_exception(IOError):\n",
" read_config_file()\n",
" \n",
"If ignore_exception is called with an exception type, all exceptions of that type are ignored. Otherwise all exceptions are ignored."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Calling super class constructor**"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"class A0(object):\n",
" pass\n",
"\n",
"class A(A0):\n",
" def hello(self):\n",
" print \"A.Hello\"\n",
" \n",
"class B(object):\n",
" def hello(self):\n",
" print \"B.Hello\"\n",
"\n",
"class C(A, B):\n",
" pass\n",
"\n",
"c = C()\n",
"c.hello()\n",
"print C.__mro__"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"A.Hello\n",
"(<class '__main__.C'>, <class '__main__.A'>, <class '__main__.A0'>, <class '__main__.B'>, <type 'object'>)\n"
]
}
],
"prompt_number": 204
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Python 3"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%%file python3.py\n",
"\n",
"# print is a function\n",
"print(\"hello\", \"world\", 2)\n",
"\n",
"# Python3 str type is what is unicode in python2\n",
"name = \"\\u0c06\"\n",
"\n",
"# It has bytes type, which is same as str in Python2\n",
"\n",
"x = b'hello'\n",
"print(x)\n",
"print(x[0])\n",
"\n",
"# some modules are moved around.\n",
"# python2 urlparse has become urllib.parse\n",
"import urllib.parse\n",
"\n",
"# some nice features!\n",
"\n",
"# keyword-only arguments\n",
"\n",
"def join(*args, sep):\n",
" return sep.join(args)\n",
"\n",
"print(join(\"hello\", \"world\", sep=\"-\"))\n",
"\n",
"def incr(x, *, amount=1):\n",
" return x+amount\n",
"\n",
"print(incr(2, amount=4))\n",
" \n",
"# new asyncio module\n",
"\n",
"# there is 2to3 utility to convert python 2 code to python 3."
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"Overwriting python3.py\n"
]
}
],
"prompt_number": 229
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"!python3 python3.py"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"hello world 2\r\n",
"b'hello'\r\n",
"104\r\n",
"hello-world\r\n",
"6\r\n"
]
}
],
"prompt_number": 230
},
{
"cell_type": "markdown",
"metadata": {},
"source": []
}
],
"metadata": {}
}
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment