From 236b8b01d5df51dd246a2c543968a92d416fc698 Mon Sep 17 00:00:00 2001 From: "J.F.J. Laros" <jlaros@obscured.morspoort.fixedpoint.nl> Date: Thu, 8 Aug 2013 18:47:45 +0200 Subject: [PATCH] Some more modifications on the classes slides. --- classes.ipynb | 450 +++++++++++++++++++++++++++++++++----------------- person.py | 29 ++++ 2 files changed, 327 insertions(+), 152 deletions(-) create mode 100644 person.py diff --git a/classes.ipynb b/classes.ipynb index 5ea4e0d..71aaf87 100644 --- a/classes.ipynb +++ b/classes.ipynb @@ -27,6 +27,22 @@ "License: [Creative Commons Attribution 3.0 License (CC-by)](http://creativecommons.org/licenses/by/3.0)" ] }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "%%html\n", + "<style type=\"text/css\">\n", + "/* Remove the vertical scrollbar added by nbconvert. */\n", + ".reveal {\n", + " overflow-y: hidden;\n", + "}\n", + "</style>" + ], + "language": "python", + "metadata": {}, + "outputs": [] + }, { "cell_type": "markdown", "metadata": { @@ -52,6 +68,7 @@ "collapsed": false, "input": [ "from IPython.display import HTML, Image, IFrame\n", + "from person import Person\n", "%pylab inline" ], "language": "python", @@ -69,7 +86,7 @@ ] } ], - "prompt_number": 128 + "prompt_number": 1 }, { "cell_type": "markdown", @@ -79,9 +96,11 @@ } }, "source": [ - "Imagine we are collecting a number of attributes of some persons:\n", + "Keeping track of attributes\n", + "===\n", + "\n", + "Suppose we want to keep track of some properties in a population:\n", "\n", - "* Eye colour.\n", "* Hair colour.\n", "* Weight.\n", "* Length." @@ -95,6 +114,9 @@ } }, "source": [ + "Non-object oriented\n", + "===\n", + "\n", "Should we use simple lists?" ] }, @@ -102,12 +124,11 @@ "cell_type": "code", "collapsed": false, "input": [ - "eye_colour = ['blue', 'blue', 'grey', 'green', 'brown']\n", "hair_colour = ['black', 'red', 'white', 'blue', 'red']\n", "weight = [80, 75, 130, 90, 64]\n", "length = [180, 174, 230, 161, 149]\n", "\n", - "eye_colour[3], hair_colour[3], weight[3], length[3]" + "hair_colour[3], weight[3], length[3]" ], "language": "python", "metadata": {}, @@ -115,13 +136,20 @@ { "metadata": {}, "output_type": "pyout", - "prompt_number": 129, + "prompt_number": 2, "text": [ - "('green', 'blue', 90, 161)" + "('blue', 90, 161)" ] } ], - "prompt_number": 129 + "prompt_number": 2 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Getting all attributes is a bit of a hastle." + ] }, { "cell_type": "code", @@ -135,22 +163,32 @@ { "metadata": {}, "output_type": "pyout", - "prompt_number": 130, + "prompt_number": 3, "text": [ "90" ] } ], - "prompt_number": 130 + "prompt_number": 3 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Getting one attribute is easy though." + ] }, { "cell_type": "markdown", "metadata": { "slideshow": { - "slide_type": "slide" + "slide_type": "subslide" } }, "source": [ + "Non-object oriented\n", + "===\n", + "\n", "Or nested lists?" ] }, @@ -158,13 +196,13 @@ "cell_type": "code", "collapsed": false, "input": [ - "person = [['blue', 'black', 80, 180],\n", - " ['blue', 'red', 75, 174],\n", - " ['grey', 'white', 130, 230],\n", - " ['green', 'blue', 90, 161],\n", - " ['brown', 'red', 64, 149]]\n", + "persons = [['black', 80, 180],\n", + " ['red', 75, 174],\n", + " ['white', 130, 230],\n", + " ['blue', 90, 161],\n", + " ['red', 64, 149]]\n", "\n", - "person[3]" + "persons[3]" ], "language": "python", "metadata": {}, @@ -172,19 +210,26 @@ { "metadata": {}, "output_type": "pyout", - "prompt_number": 131, + "prompt_number": 4, "text": [ - "['green', 'blue', 90, 161]" + "['blue', 90, 161]" ] } ], - "prompt_number": 131 + "prompt_number": 4 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now all attributes are nicely grouped." + ] }, { "cell_type": "code", "collapsed": false, "input": [ - "person[3][2]" + "persons[3][2]" ], "language": "python", "metadata": {}, @@ -192,22 +237,32 @@ { "metadata": {}, "output_type": "pyout", - "prompt_number": 132, + "prompt_number": 5, "text": [ - "90" + "161" ] } ], - "prompt_number": 132 + "prompt_number": 5 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Accessing a single attribute is a bit cryptic though." + ] }, { "cell_type": "markdown", "metadata": { "slideshow": { - "slide_type": "slide" + "slide_type": "subslide" } }, "source": [ + "Non-object oriented\n", + "===\n", + "\n", "Or a list of dictionaries?" ] }, @@ -215,13 +270,13 @@ "cell_type": "code", "collapsed": false, "input": [ - "person = [{'eye_colour': 'blue', 'hair_colour': 'black', 'weight': 80, 'length': 180},\n", - " {'eye_colour': 'blue', 'hair_colour': 'red', 'weight': 75, 'length': 174},\n", - " {'eye_colour': 'grey', 'hair_colour': 'white', 'weight': 130, 'length': 230},\n", - " {'eye_colour': 'green', 'hair_colour': 'blue', 'weight': 90, 'length': 161},\n", - " {'eye_colour': 'brown', 'hair_colour': 'red', 'weight': 64, 'length': 149}]\n", + "persons = [{'hair_colour': 'black', 'weight': 80, 'length': 180},\n", + " {'hair_colour': 'red', 'weight': 75, 'length': 174},\n", + " {'hair_colour': 'white', 'weight': 130, 'length': 230},\n", + " {'hair_colour': 'blue', 'weight': 90, 'length': 161},\n", + " {'hair_colour': 'red', 'weight': 64, 'length': 149}]\n", "\n", - "person[3]" + "persons[3]" ], "language": "python", "metadata": {}, @@ -229,19 +284,19 @@ { "metadata": {}, "output_type": "pyout", - "prompt_number": 133, + "prompt_number": 6, "text": [ - "{'eye_colour': 'green', 'hair_colour': 'blue', 'length': 161, 'weight': 90}" + "{'hair_colour': 'blue', 'length': 161, 'weight': 90}" ] } ], - "prompt_number": 133 + "prompt_number": 6 }, { "cell_type": "code", "collapsed": false, "input": [ - "person[3]['weight']" + "persons[3]['weight']" ], "language": "python", "metadata": {}, @@ -249,13 +304,13 @@ { "metadata": {}, "output_type": "pyout", - "prompt_number": 134, + "prompt_number": 7, "text": [ "90" ] } ], - "prompt_number": 134 + "prompt_number": 7 }, { "cell_type": "markdown", @@ -265,68 +320,22 @@ } }, "source": [ - "Object Oriented Programming\n", + "Classes\n", "===\n", "\n", "A class as a simple container:" ] }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "class Person(object):\n", - " weight = 80\n", - " \n", - " def __init__(self, eye_colour='unknown', hair_colour='unknown', weight=0, length=0):\n", - " self.eye_colour = eye_colour\n", - " self.hair_colour = hair_colour\n", - " if weight:\n", - " self.weight = weight\n", - " self.length = length\n", - " \n", - " def __str__(self):\n", - " return \"Eye colour: {0}, Hair colour: {1}, Weight: {2}, Length: {3}\".format(\n", - " self.eye_colour, self.hair_colour, self.weight, self.length)\n", - " \n", - " def __len__(self):\n", - " return self.length\n", - "\n", - " def feed(self, amount=3):\n", - " self.weight += amount\n", - " \n", - " def bleach(self):\n", - " self.hair_colour = 'white'\n", - " \n", - " def _convert_weight(self, multiplier):\n", - " return self.weight * multiplier\n", - " \n", - " def weight_in_pounds(self):\n", - " return self._convert_weight(2.20462)\n", - " \n", - " def weight_in_grams(self):\n", - " return self._convert_weight(1000)" - ], - "language": "python", - "metadata": { - "slideshow": { - "slide_type": "skip" - } - }, - "outputs": [], - "prompt_number": 135 - }, { "cell_type": "markdown", "metadata": { "slideshow": { - "slide_type": "slide" + "slide_type": "-" } }, "source": [ " class Person(object):\n", - " def __init__(self, eye_colour='unknown', hair_colour='unknown', weight=0, length=0):\n", - " self.eye_colour = eye_colour\n", + " def __init__(self, hair_colour='unknown', weight=0, length=0):\n", " self.hair_colour = hair_colour\n", " self.weight = weight\n", " self.length = length" @@ -336,7 +345,7 @@ "cell_type": "code", "collapsed": false, "input": [ - "someone = Person('green', 'blue', 90, 161)\n", + "someone = Person('blue', 90, 161)\n", "\n", "someone.weight" ], @@ -346,39 +355,57 @@ { "metadata": {}, "output_type": "pyout", - "prompt_number": 136, + "prompt_number": 8, "text": [ "90" ] } ], - "prompt_number": 136 + "prompt_number": 8 + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "Classes\n", + "===\n", + "\n", + "Makes initialisation a lot easier." + ] }, { "cell_type": "code", "collapsed": false, "input": [ - "person = [Person(),\n", - " Person('blue', 'red'),\n", - " Person('grey', 'white', 130, 230),\n", - " Person(weight=90),\n", - " Person(weight=64, length=149)]\n", + "persons = [Person(),\n", + " Person('red'),\n", + " Person('white', 130, 230),\n", + " Person(weight=90),\n", + " Person(weight=64, length=149)]\n", "\n", - "person[3].weight" + "persons[3].weight" ], "language": "python", - "metadata": {}, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, "outputs": [ { "metadata": {}, "output_type": "pyout", - "prompt_number": 137, + "prompt_number": 9, "text": [ "90" ] } ], - "prompt_number": 137 + "prompt_number": 9 }, { "cell_type": "markdown", @@ -387,11 +414,23 @@ "slide_type": "slide" } }, + "source": [ + "Methods\n", + "===" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, "source": [ " class Person(object):\n", " ...\n", " \n", - " def feed(self, amount=3):\n", + " def eat(self, amount=3):\n", " self.weight += amount\n", " \n", " def bleach(self):\n", @@ -402,9 +441,9 @@ "cell_type": "code", "collapsed": false, "input": [ - "person = Person('green', 'blue', 90, 161)\n", + "someone = Person('blue', 90, 161)\n", "\n", - "person.weight, person.hair_colour" + "someone.weight, someone.hair_colour" ], "language": "python", "metadata": {}, @@ -412,21 +451,21 @@ { "metadata": {}, "output_type": "pyout", - "prompt_number": 138, + "prompt_number": 10, "text": [ "(90, 'blue')" ] } ], - "prompt_number": 138 + "prompt_number": 10 }, { "cell_type": "code", "collapsed": false, "input": [ - "person.feed()\n", - "person.bleach()\n", - "person.weight, person.hair_colour" + "someone.eat()\n", + "someone.bleach()\n", + "someone.weight, someone.hair_colour" ], "language": "python", "metadata": {}, @@ -434,13 +473,13 @@ { "metadata": {}, "output_type": "pyout", - "prompt_number": 139, + "prompt_number": 11, "text": [ "(93, 'white')" ] } ], - "prompt_number": 139 + "prompt_number": 11 }, { "cell_type": "markdown", @@ -449,6 +488,18 @@ "slide_type": "slide" } }, + "source": [ + "Public and private methods\n", + "===" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, "source": [ " class Person(object):\n", " ...\n", @@ -463,11 +514,20 @@ " return self._convert_weight(1000)" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Private methods are prefixed with an underscore.\n", + "\n", + "* Note that this is a convention, it is not enforced." + ] + }, { "cell_type": "code", "collapsed": false, "input": [ - "person.weight_in_pounds(), person.weight_in_grams()" + "someone.weight_in_pounds(), someone.weight_in_grams()" ], "language": "python", "metadata": {}, @@ -475,13 +535,13 @@ { "metadata": {}, "output_type": "pyout", - "prompt_number": 140, + "prompt_number": 12, "text": [ "(205.02965999999998, 93000)" ] } ], - "prompt_number": 140 + "prompt_number": 12 }, { "cell_type": "markdown", @@ -490,23 +550,43 @@ "slide_type": "slide" } }, + "source": [ + "Class variables vs. instance variables\n", + "===" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, "source": [ " class Person(object):\n", - " weight = 80\n", + " default_weight = 80\n", " \n", - " def __init__(self, eye_colour='unknown', hair_colour='unknown', weight=0, length=0):\n", - " self.eye_colour = eye_colour\n", + " def __init__(self, hair_colour='unknown', weight=0, length=0):\n", " self.hair_colour = hair_colour\n", - " if weight:\n", - " self.weight = weight\n", + " self.weight = weight or self.default_weight\n", " self.length = length" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Class variables are defined outside the methods.\n", + "\n", + "* It is still refererenced as **self.** inside the methods." + ] + }, { "cell_type": "code", "collapsed": false, "input": [ "someone = Person()\n", + "\n", "someone.weight" ], "language": "python", @@ -515,13 +595,13 @@ { "metadata": {}, "output_type": "pyout", - "prompt_number": 142, + "prompt_number": 13, "text": [ "80" ] } ], - "prompt_number": 142 + "prompt_number": 13 }, { "cell_type": "code", @@ -536,20 +616,21 @@ { "metadata": {}, "output_type": "pyout", - "prompt_number": 143, + "prompt_number": 14, "text": [ "79" ] } ], - "prompt_number": 143 + "prompt_number": 14 }, { "cell_type": "code", "collapsed": false, "input": [ - "Person.weight = 90\n", + "Person.default_weight = 90\n", "someone = Person()\n", + "\n", "someone.weight" ], "language": "python", @@ -558,13 +639,13 @@ { "metadata": {}, "output_type": "pyout", - "prompt_number": 144, + "prompt_number": 15, "text": [ "90" ] } ], - "prompt_number": 144 + "prompt_number": 15 }, { "cell_type": "markdown", @@ -573,24 +654,55 @@ "slide_type": "slide" } }, + "source": [ + "Special methods\n", + "===" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " print someone\n", + " <__main__.Person instance at 0x321ebd8>" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, "source": [ " class Person(object):\n", " ...\n", " \n", " def __str__(self):\n", - " return \"Eye colour: {0}, Hair colour: {1}, Weight: {2}, Length: {3}\".format(\n", - " self.eye_colour, self.hair_colour, self.weight, self.length)\n", + " return \"Person with hair colour: {0}, weight: {1} and length: {2}\".format(\n", + " self.hair_colour, self.weight, self.length)\n", " \n", " def __len__(self):\n", " return self.length" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Special methods are prefixed and suffixed with double underscores.\n", + "\n", + "* There are methods for adding (**\\_\\_add\\_\\_**), subtracting (**\\_\\_sub\\_\\_**), etc." + ] + }, { "cell_type": "code", "collapsed": false, "input": [ - "print person\n", - "len(person)" + "someone = Person('blue', 90, 161)\n", + "\n", + "print someone\n", + "len(someone)" ], "language": "python", "metadata": {}, @@ -599,19 +711,31 @@ "output_type": "stream", "stream": "stdout", "text": [ - "Eye colour: green, Hair colour: white, Weight: 93, Length: 161\n" + "Person with hair colour: blue, weight: 90 and length: 161\n" ] }, { "metadata": {}, "output_type": "pyout", - "prompt_number": 126, + "prompt_number": 16, "text": [ "161" ] } ], - "prompt_number": 126 + "prompt_number": 16 + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "Class inheritance\n", + "===" + ] }, { "cell_type": "code", @@ -619,23 +743,30 @@ "input": [ "class DutchPerson(Person):\n", " def __str__(self):\n", - " return \"Oogkleur: {0}, Haarkleur: {1}, Gewicht: {2}, Lengte: {3}\".format(\n", - " self.eye_colour, self.hair_colour, self.weight, self.length)" + " return \"Persoon met haarkleur: {0}, gewicht: {1} en lengte: {2}\".format(\n", + " self.hair_colour, self.weight, self.length)" ], "language": "python", "metadata": { "slideshow": { - "slide_type": "slide" + "slide_type": "-" } }, "outputs": [], - "prompt_number": 127 + "prompt_number": 17 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "A subclass can have added functionality, or it can override some functionality." + ] }, { "cell_type": "code", "collapsed": false, "input": [ - "sinterklaas = DutchPerson('blue', 'white', 85, 191)\n", + "sinterklaas = DutchPerson('white', 85, 191)\n", "\n", "print sinterklaas" ], @@ -646,11 +777,23 @@ "output_type": "stream", "stream": "stdout", "text": [ - "Oogkleur: blue, Haarkleur: white, Gewicht: 85, Lengte: 191\n" + "Persoon met haarkleur: white, gewicht: 85 en lengte: 191\n" ] } ], - "prompt_number": 86 + "prompt_number": 18 + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "An object oriented solution for the Sequencer assignment.\n", + "===" + ] }, { "cell_type": "code", @@ -658,14 +801,14 @@ "input": [ "class Read(object):\n", " def __init__(self):\n", - " self.read = \"\"\n", + " self.read = []\n", " self.qual = []\n", " \n", " def __str__(self):\n", - " return self.read\n", + " return \"\".join(self.read)\n", " \n", - " def add(self, base):\n", - " self.read += base[0]\n", + " def append(self, base):\n", + " self.read.append(base[0])\n", " self.qual.append(base[1])\n", " \n", " def quality(self):\n", @@ -674,16 +817,18 @@ " def trim(self, score):\n", " for position in range(len(self.read) - 1, -1, -1):\n", " if self.qual[position] >= score:\n", - " return self.read[:position]" + " self.read = self.read[:position]\n", + " self.qual = self.qual[:position]\n", + " break" ], "language": "python", "metadata": { "slideshow": { - "slide_type": "slide" + "slide_type": "-" } }, "outputs": [], - "prompt_number": 7 + "prompt_number": 19 }, { "cell_type": "code", @@ -697,16 +842,17 @@ "reads = [Read() for _ in range(spots)]\n", "for tile in run:\n", " for read_id, base in enumerate(tile):\n", - " reads[read_id].add(base)\n", + " reads[read_id].append(base)\n", "\n", "for i in reads:\n", " print i, i.quality()\n", - " print i.trim(39)" + " i.trim(39)\n", + " print i, i.quality()" ], "language": "python", "metadata": { "slideshow": { - "slide_type": "slide" + "slide_type": "subslide" } }, "outputs": [ @@ -714,14 +860,14 @@ "output_type": "stream", "stream": "stdout", "text": [ - "GGTGTGATTCCCGTTCGGTGGGCCGCCTTGGGTCATTGCTCGGTTGAGGAGGGAAGACCT 30\n", - "GGTGTGATTCCCGTTCGGTGGGCCGCCTTGGGTCAT\n", - "GGCTTTAGAATGTCTCCTGCATCTGATGCTATTAAAAGCTATGTTTTTCACATAGTACGG 29\n", - "GGCTTTAGAATGTCTCCTGCATCTGATGCTATTAAAAGCTATGTTTTTCACATAGT\n" + "ATCATTAATTCTAAGTAGTCACACCGGATTAACGATCCCTCTTAGCCAACGCTTTTAGTC 29\n", + "ATCATTAATTCTAAGTAGTCACACCGGATTAACGATCCCTCTTAGCCAACGCTTT 30\n", + "TCCACTAGTGGGAATACTTAGTATTACACGGACATAGTTTACTCCCATTATATGCTAGAA 27\n", + "TCCACTAGTGGGAATACT 36\n" ] } ], - "prompt_number": 8 + "prompt_number": 20 } ], "metadata": {} diff --git a/person.py b/person.py new file mode 100644 index 0000000..857cc10 --- /dev/null +++ b/person.py @@ -0,0 +1,29 @@ +class Person(object): + default_weight = 80 + + def __init__(self, hair_colour='unknown', weight=0, length=0): + self.hair_colour = hair_colour + self.weight = weight or self.default_weight + self.length = length + + def __str__(self): + return "Person with hair colour: {0}, weight: {1} and length: {2}".format( + self.hair_colour, self.weight, self.length) + + def __len__(self): + return self.length + + def eat(self, amount=3): + self.weight += amount + + def bleach(self): + self.hair_colour = 'white' + + def _convert_weight(self, multiplier): + return self.weight * multiplier + + def weight_in_pounds(self): + return self._convert_weight(2.20462) + + def weight_in_grams(self): + return self._convert_weight(1000) -- GitLab