From c49b077ae318dd49e51099c4433c8291f6089eb5 Mon Sep 17 00:00:00 2001 From: Shashank Singh Date: Wed, 5 Feb 2020 09:13:47 -0500 Subject: [PATCH] add overrides and exercise (#4) --- ObjectOrientedPython.ipynb | 1200 ++++++++++++++++++++---------------- 1 file changed, 658 insertions(+), 542 deletions(-) diff --git a/ObjectOrientedPython.ipynb b/ObjectOrientedPython.ipynb index bbbdca5..ee9252d 100644 --- a/ObjectOrientedPython.ipynb +++ b/ObjectOrientedPython.ipynb @@ -1,543 +1,659 @@ { - "nbformat": 4, - "nbformat_minor": 0, - "metadata": { - "colab": { - "name": "ObjectOrientedPython.ipynb", - "provenance": [] - }, - "kernelspec": { - "name": "python3", - "display_name": "Python 3" - } - }, - "cells": [ - { - "cell_type": "markdown", - "metadata": { - "id": "LJ3LpvSozpAc", - "colab_type": "text" - }, - "source": [ - "# What is object oriented programming?\n", - "\n", - "Structuring programs to reflect real world notions of objects and properties and how some objects have both similarities and differences in behavior.\n", - "\n", - "## Classes\n", - "\n", - "Let us look at some built in classes and objects thus created to understand how they share behavior yet have different data." - ] - }, - { - "cell_type": "code", - "metadata": { - "id": "J3hyXIUcznVt", - "colab_type": "code", - "colab": {} - }, - "source": [ - "student = {\"name\": \"Alex\", \"age\": 19, \"major\": \"Mathematics\", \"degree\": \"BachelorOfSciece\", \"gpa\": 3.8}\n", - "pet = {\"name\": \"Scooby\", \"type\": \"Labrador\", \"age\": 2, \"color\": \"black\"}\n", - "rainbow_colors= [\"voilet\", \"indigo\", \"blue\", \"green\", \"yellow\", \"orange\", \"red\"]\n", - "rainbow_color_count = len(rainbow_colors)" - ], - "execution_count": 0, - "outputs": [] - }, - { - "cell_type": "code", - "metadata": { - "id": "qv48ZGhr23lG", - "colab_type": "code", - "colab": {} - }, - "source": [ - "print(type(student), student)\n", - "print(type(pet), pet)\n", - "print(type(rainbow_colors), rainbow_colors)\n", - "print(type(rainbow_color_count), rainbow_color_count)\n" - ], - "execution_count": 0, - "outputs": [] - }, - { - "cell_type": "code", - "metadata": { - "id": "PLm_Bdq6_xDw", - "colab_type": "code", - "colab": {} - }, - "source": [ - "def get_attributes(obj):\n", - " return [attr for attr in dir(obj) if not attr.startswith(\"_\")]" - ], - "execution_count": 0, - "outputs": [] - }, - { - "cell_type": "code", - "metadata": { - "id": "6NO-Wbcy6U-t", - "colab_type": "code", - "colab": {} - }, - "source": [ - "print(get_attributes(student))\n", - "print(get_attributes(pet))\n", - "print(get_attributes(rainbow_colors))\n", - "print(get_attributes(rainbow_color_count))" - ], - "execution_count": 0, - "outputs": [] - }, - { - "cell_type": "code", - "metadata": { - "id": "3xQmmxtB9txE", - "colab_type": "code", - "colab": {} - }, - "source": [ - "rainbow_colors.sort()\n", - "print(rainbow_colors)\n", - "student.sort()" - ], - "execution_count": 0, - "outputs": [] - }, - { - "cell_type": "code", - "metadata": { - "id": "JL7bG8uNB9Mc", - "colab_type": "code", - "colab": {} - }, - "source": [ - "print(student.items())\n", - "print(rainbow_colors.items())" - ], - "execution_count": 0, - "outputs": [] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "ZnNqn8GEBheJ", - "colab_type": "text" - }, - "source": [ - "### Objects belonging to the same class have common attributes. \n", - "\n", - "These attributes can be either functions (also called methods) or data (variables).\n", - "\n", - "These common attributes give all objects of a class common behavior.\n", - "\n", - "For example, all lists can be sorted, reversed, you can calculate their length and do comprehensions on them." - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "5qNQOtl8vipq", - "colab_type": "text" - }, - "source": [ - "### Let's define a basic person class. The simplest class definition can look like:" - ] - }, - { - "cell_type": "code", - "metadata": { - "id": "epIQv3ZBBXot", - "colab_type": "code", - "colab": {} - }, - "source": [ - "class Person:\n", - " pass" - ], - "execution_count": 0, - "outputs": [] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "fWDjmhiGwTTB", - "colab_type": "text" - }, - "source": [ - "Now, we can create objects of the person class." - ] - }, - { - "cell_type": "code", - "metadata": { - "id": "7E_SPrX7GlEJ", - "colab_type": "code", - "colab": {} - }, - "source": [ - "p1 = Person()\n", - "p2 = Person()" - ], - "execution_count": 0, - "outputs": [] - }, - { - "cell_type": "code", - "metadata": { - "id": "VcDNIQo_HKUS", - "colab_type": "code", - "colab": {} - }, - "source": [ - "type(p1)" - ], - "execution_count": 0, - "outputs": [] - }, - { - "cell_type": "code", - "metadata": { - "id": "AWC2i4hywt8i", - "colab_type": "code", - "colab": {} - }, - "source": [ - "isinstance(p2, Person)" - ], - "execution_count": 0, - "outputs": [] - }, - { - "cell_type": "code", - "metadata": { - "id": "NVFK2jxKwx-5", - "colab_type": "code", - "colab": {} - }, - "source": [ - "p1 == p2" - ], - "execution_count": 0, - "outputs": [] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "k9lP_gmhxkVm", - "colab_type": "text" - }, - "source": [ - "## Class objects support two kinds of operations: attribute references and instantiation. \n", - "https://docs.python.org/3/tutorial/classes.html\n", - "\n", - "Let's look at examples of both" - ] - }, - { - "cell_type": "code", - "metadata": { - "id": "ERaasbfbxhiq", - "colab_type": "code", - "colab": {} - }, - "source": [ - "class Person:\n", - " species = \"Homo Sapeins\" # property shared across all objects\n", - "\n", - " def greet(self):\n", - " # self is a reference to the instance calling this method\n", - " return f\"Hello friend!\"\n", - "\n", - "p1 = Person()\n", - "p2 = Person()\n", - "print(p1.species)\n", - "print(p2.greet())" - ], - "execution_count": 0, - "outputs": [] - }, - { - "cell_type": "code", - "metadata": { - "id": "81WGtXLw0enS", - "colab_type": "code", - "colab": {} - }, - "source": [ - "print(p1 == p2)\n", - "print(p1.species == p2.species)" - ], - "execution_count": 0, - "outputs": [] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "hARyQq_LxjXm", - "colab_type": "text" - }, - "source": [ - "### Instantiation operation\n", - "\n", - "In the Person class above, when you call Person(), python gives you an empty object. Each time you call `Person()`, a new object is returned. When you call `.greet()` on one such object, Python passes a reference of the object itself in `self`. \n", - "\n", - "If you want to construct an object with some state / parameters, you can define the `__init__` method\n" - ] - }, - { - "cell_type": "code", - "metadata": { - "id": "-KIqZfNiCvzF", - "colab_type": "code", - "colab": {} - }, - "source": [ - "class Person:\n", - " species = \"Homo Sapeins\" # property shared across all objects\n", - " \n", - " def __init__(self, name):\n", - " self.name = name # store given name in the instance\n", - "\n", - " def greet(self, person):\n", - " # self is a reference to the instance calling this method\n", - " return \"Hello \" + person.name + \"! My name is \" + self.name # use instance specific data" - ], - "execution_count": 0, - "outputs": [] - }, - { - "cell_type": "code", - "metadata": { - "id": "aRH2BUPJC1Gh", - "colab_type": "code", - "colab": {} - }, - "source": [ - "p1 = Person(\"Tom\")\n", - "p2 = Person(\"Jerry\")\n", - "p1.greet(p2)" - ], - "execution_count": 0, - "outputs": [] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "KQWpy_E8AH8Z", - "colab_type": "text" - }, - "source": [ - "You can modify an objects attributes after instantiation as well. General convention is that an attribute with an _ prefix is intended to not be modified by a caller outside." - ] - }, - { - "cell_type": "code", - "metadata": { - "id": "cmUsIWCzAd0m", - "colab_type": "code", - "colab": {} - }, - "source": [ - "from datetime import datetime, date\n", - "\n", - "class Person:\n", - " species = \"Homo Sapeins\" # property shared across all objects\n", - " \n", - " def __init__(self, name, dob, ssn=None):\n", - " self.name = name\n", - " self._dob = dob\n", - " self._ssn = ssn\n", - "\n", - " def greet(self, person):\n", - " # self is a reference to the instance calling this method\n", - " return \"Hello \" + person.name + \"! My name is \" + self.name \n", - "\n", - " def age(self):\n", - " return datetime.now().date().year - self._dob.year" - ], - "execution_count": 0, - "outputs": [] - }, - { - "cell_type": "code", - "metadata": { - "id": "vsIzS5BPAm_v", - "colab_type": "code", - "colab": {} - }, - "source": [ - "p1 = Person(\"Shashank\", date(2000, 1, 1), \"abc-def-ghij\")\n", - "print(p1.greet(p2))\n", - "print(p1.age())\n", - "p1.name = \"Shashank Singh\"\n", - "p1.greet(p2)\n", - "\n", - "p1._ssn = \"111-11-1111\" # not advisable unless you know what you are doing..." - ], - "execution_count": 0, - "outputs": [] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "j3AFX7oDYbfG", - "colab_type": "text" - }, - "source": [ - "## Excercise\n", - "\n", - "Create a function that finds the youngest and the oldest person from a list of people and the makes the oldest greet the youngest.\n", - "\n", - "\n", - "\n", - "\n" - ] - }, - { - "cell_type": "code", - "metadata": { - "id": "nE-IQC4vYa2T", - "colab_type": "code", - "colab": {} - }, - "source": [ - "def old_greets_new(people):\n", - " oldest = youngest = people[0]\n", - " for person in people:\n", - " if person.age() < youngest.age():\n", - " youngest = person\n", - " elif person.age() > oldest.age():\n", - " oldest = person \n", - " return oldest.greet(youngest)\n", - "\n", - "legends = [Person(\"Maradona\", date(1960, 10, 30)), Person(\"Zidane\", date(1972, 6, 23)), Person(\"Messi\", date(1987, 6, 24))]\n", - "print(old_greets_new(legends))" - ], - "execution_count": 0, - "outputs": [] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "edtnEM5CG3dW", - "colab_type": "text" - }, - "source": [ - "# Inheritance\n", - "\n" - ] - }, - { - "cell_type": "code", - "metadata": { - "id": "s5WGFNOfIMvq", - "colab_type": "code", - "colab": {} - }, - "source": [ - "class Person:\n", - " def __init__(self, name):\n", - " self.name = name\n", - "\n", - " def greet(self, person):\n", - " # self is a reference to the instance calling this method\n", - " return \"Hello \" + person.name + \"! My name is \" + self.name \n", - "\n", - "\n", - "class Student(Person): # A student inherits properties from person\n", - "\n", - " def __init__(self, name):\n", - " super().__init__(name) # call the parent class constructor\n", - " self.score = 0\n", - " self.assignments = []\n", - "\n", - " def do_assignment(self, assignment):\n", - " self.assignments.append(\"solved: \" + assignment)\n", - "\n", - "\n", - "class Professor(Person): # A professor is also a person, inheriting person like behavior and properties\n", - "\n", - " def __init__(self, name, dept):\n", - " super().__init__(name) # call the parent class constructor\n", - " self.dept = dept\n", - "\n", - " def grade_assignments(self, student):\n", - " for assignment in student.assignments:\n", - " student.score += 1\n" - ], - "execution_count": 0, - "outputs": [] - }, - { - "cell_type": "code", - "metadata": { - "id": "NKdblbEdIP4A", - "colab_type": "code", - "colab": {} - }, - "source": [ - "sam = Student(\"Sam\")\n", - "sam.do_assignment(\"Lesson1\")\n", - "brooks = Professor(\"Brooks\", \"computer-science\")\n", - "brooks.grade_assignments(sam)\n", - "sam.score" - ], - "execution_count": 0, - "outputs": [] - }, - { - "cell_type": "code", - "metadata": { - "id": "O0kd1pJHRrGP", - "colab_type": "code", - "colab": {} - }, - "source": [ - "isinstance(sam, Person)" - ], - "execution_count": 0, - "outputs": [] - }, - { - "cell_type": "code", - "metadata": { - "id": "8QzjMiusSf_4", - "colab_type": "code", - "colab": {} - }, - "source": [ - "isinstance(brooks, Person)" - ], - "execution_count": 0, - "outputs": [] - }, - { - "cell_type": "code", - "metadata": { - "id": "Jaonoas0SjiY", - "colab_type": "code", - "colab": {} - }, - "source": [ - "isinstance(brooks, Student)" - ], - "execution_count": 0, - "outputs": [] - }, - { - "cell_type": "code", - "metadata": { - "id": "tOimkaRoSmsP", - "colab_type": "code", - "colab": {} - }, - "source": [ - "brooks.greet(sam)" - ], - "execution_count": 0, - "outputs": [] - } - ] -} \ No newline at end of file + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "LJ3LpvSozpAc" + }, + "source": [ + "# What is object oriented programming?\n", + "\n", + "Structuring programs to reflect real world notions of objects and properties and how some objects have both similarities and differences in behavior.\n", + "\n", + "## Classes\n", + "\n", + "Let us look at some built in classes and objects thus created to understand how they share behavior yet have different data." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "J3hyXIUcznVt" + }, + "outputs": [], + "source": [ + "student = {\"name\": \"Alex\", \"age\": 19, \"major\": \"Mathematics\", \"degree\": \"BachelorOfSciece\", \"gpa\": 3.8}\n", + "pet = {\"name\": \"Scooby\", \"type\": \"Labrador\", \"age\": 2, \"color\": \"black\"}\n", + "rainbow_colors= (\"voilet\", \"indigo\", \"blue\", \"green\", \"yellow\", \"orange\", \"red\")\n", + "model_name = \"Toyota Prius\"\n", + "model_colors = [\"magenta\", \"cyan\"]\n", + "model_year = 2020" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "qv48ZGhr23lG" + }, + "outputs": [], + "source": [ + "def get_attributes(obj):\n", + " return [attr for attr in dir(obj) if not attr.startswith(\"_\")]\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "PLm_Bdq6_xDw" + }, + "outputs": [], + "source": [ + "for var in (student, pet, rainbow_colors, model_name, model_colors, model_year):\n", + " print(type(var), get_attributes(var))\n", + " input()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "6NO-Wbcy6U-t" + }, + "outputs": [], + "source": [ + "for color in rainbow_colors: # can iterate over lists, tuples and strings\n", + " print(color)\n", + "\n", + "for color in model_colors:\n", + " print(color)\n", + " \n", + "for char in model_name:\n", + " print(char)\n", + "\n", + "print(rainbow_colors[0:3]) # can also slice through lists, tuples and strings\n", + "print(model_colors[0:3])\n", + "print(model_name[0:3])\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "for digit in model_year:\n", + " print(digit)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "model_year[0:3]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "3xQmmxtB9txE" + }, + "outputs": [], + "source": [ + "students.sort()\n", + "print(student)\n", + "\n", + "rainbow_colors.sort() # tuples and lift are different when it comes to mutability" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "JL7bG8uNB9Mc" + }, + "outputs": [], + "source": [ + "print(student.items())\n", + "student.sort() # dictionaries have different behavior" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "ZnNqn8GEBheJ" + }, + "source": [ + "### Objects belonging to the same class have common attributes / behavior. \n", + "\n", + "These attributes can be either functions (also called methods) or data (variables).\n", + "\n", + "These common attributes give all objects of a class common behavior.\n", + "\n", + "For example, all lists can be sorted, reversed, you can calculate their length and do comprehensions on them." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "5qNQOtl8vipq" + }, + "source": [ + "### Let's define a basic person class. The simplest class definition can look like:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "epIQv3ZBBXot" + }, + "outputs": [], + "source": [ + "class Person:\n", + " pass" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "fWDjmhiGwTTB" + }, + "source": [ + "Now, we can create objects of the person class." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "7E_SPrX7GlEJ" + }, + "outputs": [], + "source": [ + "p1 = Person()\n", + "p2 = Person()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "VcDNIQo_HKUS" + }, + "outputs": [], + "source": [ + "type(p1)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "AWC2i4hywt8i" + }, + "outputs": [], + "source": [ + "isinstance(p2, Person)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "NVFK2jxKwx-5" + }, + "outputs": [], + "source": [ + "p1 == p2" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "k9lP_gmhxkVm" + }, + "source": [ + "## Class objects support two kinds of operations: attribute references and instantiation. \n", + "https://docs.python.org/3/tutorial/classes.html\n", + "\n", + "Let's look at examples of both" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "ERaasbfbxhiq" + }, + "outputs": [], + "source": [ + "class Person:\n", + " species = \"Homo Sapeins\" # property shared across all objects\n", + "\n", + " def greet(self):\n", + " # self is a reference to the instance calling this method\n", + " return f\"Hello friend!\"\n", + "\n", + "p1 = Person()\n", + "p2 = Person()\n", + "print(p1.species)\n", + "print(p2.greet())" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "81WGtXLw0enS" + }, + "outputs": [], + "source": [ + "print(p1 == p2)\n", + "print(p1.species == p2.species)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "hARyQq_LxjXm" + }, + "source": [ + "### Instantiation operation\n", + "\n", + "In the Person class above, when you call Person(), python gives you an empty object. Each time you call `Person()`, a new object is returned. When you call `.greet()` on one such object, Python passes a reference of the object itself in `self`. \n", + "\n", + "If you want to construct an object with some state / parameters, you can define the `__init__` method\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "-KIqZfNiCvzF" + }, + "outputs": [], + "source": [ + "class Person:\n", + " species = \"Homo Sapeins\" # property shared across all objects\n", + " \n", + " def __init__(self, name):\n", + " self.name = name # store given name in the instance\n", + "\n", + " def greet(self, person):\n", + " # self is a reference to the instance calling this method\n", + " return \"Hello \" + person.name + \"! My name is \" + self.name # use instance specific data" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "aRH2BUPJC1Gh" + }, + "outputs": [], + "source": [ + "p1 = Person(\"Tom\")\n", + "p2 = Person(\"Jerry\")\n", + "p1.greet(p2)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "KQWpy_E8AH8Z" + }, + "source": [ + "#### Instance attributes\n", + "\n", + "Having attributes and functions that the class instances share is useful, but allowing each instance to store its own data is the more common use case. This way, class instances have similar behavior but conceptually represent a unique real-world entity.\n", + "\n", + "The `__init__` method is what python calls during object creation. You can pass arguments to this method that can be used or stored in the isntance itself.\n", + "\n", + "You can modify an objects attributes after instantiation as well. General convention is that an attribute with an _ prefix is intended to not be modified by a caller outside." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "cmUsIWCzAd0m" + }, + "outputs": [], + "source": [ + "from datetime import datetime, date\n", + "\n", + "class Person:\n", + " species = \"Homo Sapeins\" # property shared across all objects\n", + " \n", + " def __init__(self, name, dob, ssn=None):\n", + " self.name = name\n", + " self._dob = dob\n", + " self._ssn = ssn\n", + "\n", + " def greet(self, person):\n", + " # self is a reference to the instance calling this method\n", + " return \"Hello \" + person.name + \"! My name is \" + self.name \n", + "\n", + " def age(self):\n", + " return datetime.now().date().year - self._dob.year" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "vsIzS5BPAm_v" + }, + "outputs": [], + "source": [ + "p1 = Person(\"Shashank\", date(2000, 1, 1), \"abc-def-ghij\") # passing arguments to instance construction\n", + "print(p1.greet(p2))\n", + "print(p1.age()) # method called on instance that can use its associated data attributes\n", + "p1.name = \"Shashank Singh\"\n", + "p1.greet(p2)\n", + "\n", + "p1._ssn = \"111-11-1111\" # not advisable unless you know what you are doing..." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "j3AFX7oDYbfG" + }, + "source": [ + "## Excercise\n", + "\n", + "Create a function that finds the youngest and the oldest person from a list of people and the makes the oldest greet the youngest.\n", + "\n", + "\n", + "\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "nE-IQC4vYa2T" + }, + "outputs": [], + "source": [ + "def old_greets_new(people):\n", + " oldest = youngest = people[0]\n", + " for person in people:\n", + " if person.age() < youngest.age():\n", + " youngest = person\n", + " elif person.age() > oldest.age():\n", + " oldest = person \n", + " return oldest.greet(youngest)\n", + "\n", + "legends = [Person(\"Maradona\", date(1960, 10, 30)), Person(\"Zidane\", date(1972, 6, 23)), Person(\"Messi\", date(1987, 6, 24))]\n", + "print(old_greets_new(legends))" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "edtnEM5CG3dW" + }, + "source": [ + "# Inheritance\n", + "\n", + "\n", + "Inheritance allows objects of derived classes to 'inherit' attributes from the base class and modify some inherited behavior if needed.\n", + "\n", + "\n", + "For example, a base class `Triangle` could have a method called `area` that returns `1/2 * base * height`. We could have a derived class called `EquilateralTriangle` that only needs one dimension to be specified and it can determine the area with a different formula...\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import math\n", + "\n", + "class Triangle:\n", + " def __init__(self, base, height):\n", + " self.base = base\n", + " self.height = height\n", + " \n", + " def area(self):\n", + " return 0.5 * self.base * self.height\n", + "\n", + " \n", + "class EquilateralTriangle(Triangle):\n", + " def __init__(self, side):\n", + " height = math.sin(math.radians(60)) * side\n", + " super().__init__(base=side, height=height) # calculate height and call parent constructor\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "triangle = Triangle(10, 10) # needs both base and height explicitly\n", + "print(triangle.area())\n", + "eq_triangle = EquilateralTriangle(10)\n", + "print(eq_triangle.area()) # note that it did not have to implement its own area, it 'inherited' it " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In our Person example, we can create sub-classes called Student and Professor, who are both people." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "s5WGFNOfIMvq" + }, + "outputs": [], + "source": [ + "class Person:\n", + " def __init__(self, name):\n", + " self.name = name\n", + "\n", + " def greet(self, person):\n", + " return \"Hello \" + person.name + \"! My name is \" + self.name \n", + "\n", + "\n", + "class Student(Person): # A student inherits properties from person\n", + "\n", + " def __init__(self, name):\n", + " super().__init__(name) # call the parent class constructor\n", + " self.score = 0\n", + " self.assignments = []\n", + "\n", + " def do_assignment(self, assignment):\n", + " self.assignments.append(\"solved: \" + assignment)\n", + "\n", + "\n", + "class Professor(Person): # A professor is also a person, inheriting person like behavior and properties\n", + "\n", + " def __init__(self, name, dept):\n", + " super().__init__(name) # call the parent class constructor\n", + " self.dept = dept\n", + "\n", + " def grade_assignments(self, student):\n", + " for assignment in student.assignments:\n", + " student.score += 1\n", + " \n", + " def greet(self, person): # this 'overrides' the greeting method provided by the parent\n", + " return \"Hello \" + person.name + \"! I am Dr. \" + self.name \n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "NKdblbEdIP4A" + }, + "outputs": [], + "source": [ + "sam = Student(\"Sam\")\n", + "sam.do_assignment(\"Lesson1\")\n", + "brooks = Professor(\"Brooks\", \"computer-science\")\n", + "brooks.grade_assignments(sam)\n", + "sam.score\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "O0kd1pJHRrGP" + }, + "outputs": [], + "source": [ + "isinstance(sam, Person)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "8QzjMiusSf_4" + }, + "outputs": [], + "source": [ + "isinstance(brooks, Person)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "Jaonoas0SjiY" + }, + "outputs": [], + "source": [ + "isinstance(brooks, Student)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "sam.greet(brooks)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "brooks.greet(sam)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exercise\n", + "\n", + "1. Write a Python class named Circle constructed by a radius and two methods which will compute the area and the perimeter of a circle.\n", + "\n", + "2. Use `dir` on an instance of a circle thus created. Change the radius attribute and calculate the area again.\n", + "\n", + "3. Rewrite your stock exercise with classes with the added functionality that the file now contains another column called person. Each person can own multiple stocks of multiple companies. Write a method in the Person class that gives the total stocks and their value of a particular company. Write another method that gives the total portfolio value." + ] + } + ], + "metadata": { + "colab": { + "name": "ObjectOrientedPython.ipynb", + "provenance": [] + }, + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.9" + } + }, + "nbformat": 4, + "nbformat_minor": 1 +}