{ "cells": [ { "cell_type": "markdown", "id": "c64d49df", "metadata": {}, "source": [ "# Python Basics - 08. Object-Oriented Programming (OOP)\n", "\n", "Python is an object-oriented language. OOP allows developers to bundle properties (data) and behaviors (methods) into individual entities called **Objects**. This notebook explains how to define and use objects and their relationships." ] }, { "cell_type": "markdown", "id": "af7a8d02", "metadata": { "language": "markdown" }, "source": [ "## Download Notebook\n", "\n", "{download}`Download this notebook <08_classes_and_objects.ipynb>`\n" ] }, { "cell_type": "markdown", "id": "5b87583f", "metadata": {}, "source": [ "## 1. Defining Classes and Creating Objects\n", "\n", "- `class`: The keyword to define a new class (a blueprint for creating objects).\n", "- `__init__`: The \"constructor\" or initialization method. It sets up the starting state of the object properties.\n", "- `self`: Refers to the specific instance of the object being operated on." ] }, { "cell_type": "code", "execution_count": null, "id": "de6109d0", "metadata": {}, "outputs": [], "source": [ "class Dog:\n", " # Class Attribute (shared by every Dog instance)\n", " species = \"Canis familiaris\"\n", "\n", " def __init__(self, name, age):\n", " # Instance Attributes (unique to each Dog instance)\n", " self.name = name\n", " self.age = age\n", "\n", " # An instance Method\n", " def description(self):\n", " return f\"{self.name} is {self.age} years old.\"\n", "\n", " def speak(self, sound):\n", " return f\"{self.name} says '{sound}'!\"\n", "\n", "# Instantiating completely separate objects from the 'Dog' blueprint\n", "buddy = Dog(\"Buddy\", 9)\n", "miles = Dog(\"Miles\", 4)\n", "\n", "print(f\"Species: {buddy.species}\")\n", "print(buddy.description())\n", "print(miles.speak(\"Woof woof\"))" ] }, { "cell_type": "markdown", "id": "ab32605f", "metadata": {}, "source": [ "## 2. Inheritance\n", "\n", "Inheritance allows a new class (Child Class) to adopt the methods and attributes of another class (Parent Class), promoting code reuse." ] }, { "cell_type": "code", "execution_count": null, "id": "1001cca7", "metadata": {}, "outputs": [], "source": [ "# GoldenRetriever inherits from the Parent 'Dog'\n", "class GoldenRetriever(Dog):\n", " \n", " # We can override the speak method specifically for this breed\n", " def speak(self, sound=\"Bark\"):\n", " # 'super()' lets us call methods defined in the parent class\n", " return super().speak(sound)\n", "\n", "goldie = GoldenRetriever(\"Goldie\", 5)\n", "\n", "# Still has access to description() defined in Dog\n", "print(goldie.description())\n", "\n", "# Using the overridden parent class logic\n", "print(goldie.speak()) # Uses the default \"Bark\"\n", "print(goldie.speak(\"Arf\")) # We can still provide a custom sound" ] }, { "cell_type": "markdown", "id": "aa36ae5d", "metadata": {}, "source": [ "## 3. Magic Methods and Polymorphism\n", "\n", "Magic methods (also called dunder methods) let your objects integrate with Python syntax.\n", "Polymorphism means different classes can provide the same method name with class-specific behavior." ] }, { "cell_type": "code", "execution_count": null, "id": "a1ac76f8", "metadata": {}, "outputs": [], "source": [ "class Vector2D:\n", " def __init__(self, x, y):\n", " self.x = x\n", " self.y = y\n", "\n", " # __repr__ controls the object's developer-friendly print format.\n", " def __repr__(self):\n", " return f\"Vector2D(x={self.x}, y={self.y})\"\n", "\n", " # __add__ enables using + between two Vector2D instances.\n", " def __add__(self, other):\n", " return Vector2D(self.x + other.x, self.y + other.y)\n", "\n", "v1 = Vector2D(1, 2)\n", "v2 = Vector2D(3, 4)\n", "print(v1 + v2)\n", "\n", "# Polymorphism demo:\n", "# different classes share the same method name with different behavior.\n", "class Cat:\n", " def speak(self):\n", " return \"Meow\"\n", "\n", "class Bird:\n", " def speak(self):\n", " return \"Tweet\"\n", "\n", "def animal_sound(animal):\n", " print(animal.speak())\n", "\n", "animal_sound(Cat())\n", "animal_sound(Bird())" ] }, { "cell_type": "markdown", "id": "94f62fb1", "metadata": {}, "source": [ "## 4. Superclass (Base Class) and `super()`\n", "\n", "A **Superclass** (also called a base class) provides shared attributes and behavior.\n", "A **Subclass** extends or customizes that behavior.\n", "\n", "`super()` lets a subclass call methods from its superclass without hardcoding the class name.\n", "This makes inheritance code cleaner and easier to maintain." ] }, { "cell_type": "code", "execution_count": null, "id": "08407a8f", "metadata": {}, "outputs": [], "source": [ "class Animal:\n", " \"\"\"Superclass: defines behavior common to all animals.\"\"\"\n", "\n", " def __init__(self, name):\n", " self.name = name\n", "\n", " def speak(self):\n", " return f\"{self.name} makes a sound\"\n", "\n", "\n", "class Dog(Animal):\n", " \"\"\"Subclass of Animal: extends and overrides behavior.\"\"\"\n", "\n", " def __init__(self, name, breed):\n", " # Use super() to reuse superclass initialization logic.\n", " super().__init__(name)\n", " self.breed = breed\n", "\n", " def speak(self):\n", " # Optional: call superclass behavior first, then customize.\n", " base = super().speak()\n", " return f\"{base}; {self.name} barks\"\n", "\n", "\n", "d = Dog(\"Buddy\", \"Golden Retriever\")\n", "print(d.name)\n", "print(d.breed)\n", "print(d.speak())" ] } ], "metadata": { "language_info": { "name": "python" } }, "nbformat": 4, "nbformat_minor": 5 }