Try   HackMD

Object‑oriented programming organises code around classes (blueprints) and the objects built from them. Data lives in attributes, actions live in methods.

Defining a Class and Making Instances

class Dog:
    species = "Canis lupus"              # one value shared by all dogs

    def __init__(self, name):            # runs when a dog is created
        self.name = name                 # unique to each dog

    def speak(self):
        return f"{self.name} says Woof!"

Dog("Fido") makes a new dog. Its name is just for Fido, while species lives once in the class. Every instance method needs self as the first argument.

Instance versus Class Attributes

fido = Dog("Fido")
fido.species = "Mutant"            # affects only this object
print(Dog.species)                 # still "Canis lupus"

An attribute set on one object stays on that object. A value written in the class body is shared by all objects.

__str__ and __repr__

class Car:
    def __init__(self, make, year):
        self.make, self.year = make, year

    def __str__(self):             # friendly text for print()
        return f"{self.year} {self.make}"

    def __repr__(self):            # precise text for debugging
        return f"Car({self.make!r}, {self.year})"

__str__ supplies the readable string shown by print. __repr__ supplies an unambiguous string shown in interactive sessions and logs.

Inheritance (is‑a relationship)

class Animal:
    def __init__(self, name):
        self.name = name
    def speak(self):
        raise NotImplementedError

class Cat(Animal):
    def speak(self):
        return "Meow!"

A child class re‑uses code from its parent and changes only what is different. If the parent’s constructor also needs to run, call it with super().__init__(...).

Composition (has‑a relationship)

class Engine:
    def __init__(self, hp):
        self.hp = hp

class Vehicle:
    def __init__(self, engine):
        self.engine = engine        # Vehicle owns an Engine

Composition stores one object inside another. Swapping the owned part (for example, a stronger engine) does not require rewriting the outer class.

Encapsulation

Name‑mangling

class BankAccount:
    def __init__(self, balance):
        self.__balance = balance
    def deposit(self, amount):
        self.__balance += amount

Two underscores change __balance into a longer internal name, so outside code won't touch it by mistake.

property for Controlled Access

class Celsius:
    def __init__(self, deg):
        self._deg = deg

    @property
    def deg(self):                  # getter
        return self._deg

    @deg.setter
    def deg(self, value):           # setter
        if value < -273.15:
            raise ValueError("Below absolute zero")
        self._deg = value

The @property decorator lets you read temp.deg like a normal attribute which we called it getter, while the paired setter runs validation whenever you assign to it.

Class Data, Class Methods, and Static Methods

class Circle:
    pi = 3.14159                        # stored once in the class

    def __init__(self, r):
        self.r = r                      # radius belongs to one circle

    @classmethod
    def unit(cls):                      # alternative constructor
        return cls(1)

    @staticmethod
    def area(r):                        # helper that needs no object
        return Circle.pi * r * r

pi is a class constant. The unit method receives the class (cls) so it can create Circle objects and still work for subclasses. The area method is labelled @staticmethod because it relies on neither self nor cls; it is simply grouped with the class for convenience and is called as Circle.area(5).

Polymorphism

class Rectangle:
    def __init__(self, w, h):
        self.w, self.h = w, h
    def area(self):
        return self.w * self.h

class Circle:
    def __init__(self, r):
        self.r = r
    def area(self):
        return 3.14 * self.r ** 2

shapes = [Rectangle(3, 4), Circle(2)]
areas  = [s.area() for s in shapes]     # same call, different maths

Different classes can answer the same method name (area). You can loop over mixed objects without checking their types.

Operator Overloading

class Vector2D:
    def __init__(self, x, y):
        self.x, self.y = x, y

    def __add__(self, other):           # enables v + w
        return Vector2D(self.x + other.x, self.y + other.y)

    def __len__(self):                  # enables len(v)
        return 2

Writing special double‑underscore methods teaches Python's built‑in operators how to work with your objects, making them feel like native types.

Quick Reference: Common Dunder Methods

Task Method examples
Text __str__, __repr__
Math __add__, __sub__, __mul__, …
Compare __lt__, __eq__, __hash__
Sequence __len__, __getitem__, __iter__

Keywords

  • Object Oriented Programming (OOP) (物件導向程式設計): A programming paradigm that organizes code using objects and classes to model real-world entities and relationships.
  • class (類別): A blueprint for creating objects that defines attributes and methods.
  • object (物件): An instance of a class containing data (attributes) and behavior (methods).
  • method (方法): A function defined within a class that operates on instances of that class.
  • attribute (屬性): A variable that is bound to an object or class, holding data relevant to that object.
  • constructor (建構子): A special method, typically __init__, that initializes a new object's state when it is created.
  • destructor (解構子): A special method, typically __del__, that is called when an object is about to be destroyed, used for cleanup.
  • dunder method (雙底線方法): A special method with double underscores before and after its name (e.g., __init__, __str__) that enables built-in behaviors.
  • inheritance (繼承): A mechanism where a new class (child) derives attributes and methods from an existing class (parent), representing a "is-a" relationship.
  • parent(base) class (父類別/基礎類別): A class whose properties and methods are inherited by another class.
  • child(derived) class (子類別/衍生類別): A class that inherits from a parent class and can extend or override its behavior.
  • override (覆寫): To provide a new implementation for an inherited method in a child class.
  • composition (複合): A design principle where a class is composed of one or more objects of other classes, representing a "has-a" relationship.
  • encapsulation (封裝): The bundling of data and methods within a class, restricting access to internal details and protecting object integrity.
  • private data (私有資料): Attributes intended to be hidden from outside access, usually denoted with a leading underscore (e.g., _data).
  • public data (公有資料): Attributes that are accessible from outside the class without restrictions.
  • public method (公有方法): Methods that are accessible from outside the class without restrictions.
  • private method (私有方法): A method intended for internal use within a class, typically indicated by a leading underscore.
  • utility method (工具方法): A method that performs a supportive or common function, often independent of instance-specific data.
  • class method (類別方法): A method bound to the class rather than an instance, marked with the @classmethod decorator, and takes the class as its first parameter.
  • class attribute (類別屬性): An attribute that is shared among all instances of a class.
  • polymorphism (多型): The ability for different classes to be treated through a common interface, often by overriding methods.
  • function overloading (函數重載): Defining multiple functions with the same name but different parameters.
  • operator overloading (運算子重載): Defining special methods to customize the behavior of built-in operators for user-defined classes.
  • method overriding (方法覆寫): Providing a new implementation for a method inherited from a parent class, allowing the child class to customize behavior.