oop

#oop(OOP) modern tutorial

1. oop overview

oop (Object‑Oriented Programming, OOP) is a programming paradigm with "object interaction" as its core. It packages data (properties) and logic (methods) for operating data into an independent individual - an object. In this way, the code is organized in a way that is closer to human understanding of the world. For example, think of "student" as an entity with name, score attributes, and actions such as "hand in homework" and "print results", rather than variables and functions scattered around.

1.1 Comparison with procedural programming

In order to intuitively feel the advantages of OOP, we use a small example of performance management to compare the two paradigms:

FeaturesProcedure-oriented programmingoop
Core Organizational UnitFunctionObject
Design ideasTop-down decomposition into steps (input → calculation → output)Bottom-up abstraction of "entities" in reality/business
Data and operationsCompletely separated, data depends on global variables or function parametersData is bound inside the object and can be hidden from the outside
Code maintainabilityModifying the data structure may affect a bunch of related functionsModifying the internal implementation only requires changing the corresponding class/object
Code reuse methodsExtract functions, copy and pasteInheritance, combination, polymorphism

2. OOP basics in Python

Python is a dynamic language that fully supports OOP, but it does not force you to use OOP. Small scripts can continue to maintain a process-oriented style, while OOP is highly recommended for larger projects to manage complexity.

2.1 Classes and Objects

In Python:

  • Class: Create a "template" or "blueprint" for an object, which specifies what properties and methods the object should have.
  • Object: A specific individual instantiated by a class, such as "Zhang San" and "Li Si" created through the "Student Template".

Basic class definition

class Student:
    """学生类示例:记录姓名、分数并打印成绩"""

    # __init__ 是初始化方法,创建对象时自动调用
    # self 代表即将创建的对象本身,必须显式写出
    def __init__(self, name: str, score: float):
        self.name = name      # 实例属性:每个对象单独持有
        self.score = score

    def print_score(self) -> None:
        """打印格式化的成绩信息"""
        print(f'📚 {self.name} 的成绩:{self.score}')

2.2 Creating and using objects

# 实例化两个不同的 Student 对象
bart = Student('Bart Simpson', 59)
lisa = Student('Lisa Simpson', 87)

# 访问实例属性
print(f"Lisa 的姓名:{lisa.name}")   # 输出:Lisa 的姓名:Lisa Simpson

# 调用实例方法
bart.print_score()   # 输出:📚 Bart Simpson 的成绩:59
lisa.print_score()   # 输出:📚 Lisa Simpson 的成绩:87

💡 Tips: All methods in Python must explicitly receiveselfParameters, but you don’t need to pass them in yourself when calling, Python will handle it automatically.


3. Three core features of object-oriented

The three major characteristics are the key to distinguishing OOP from other paradigms, and they are also frequently tested in interviews.

3.1 Encapsulation

Encapsulation has two meanings:

  1. Data Binding: Package properties and methods in the same class.
  2. Information Hiding: Only necessary interfaces are exposed to the outside world, and internal implementation details (such as the calculation logic of account balances) are not allowed to be modified at will.

Python uses double underscore prefix__ to simulate private properties/methods (actually a name mangling:_类名__属性名, not really private, but enough to express the "no direct access" intent).

Encapsulation example: bank account

class BankAccount:
    def __init__(self, owner: str, initial_balance: float = 0.0):
        self.owner = owner            # 公开属性,可以直接访问
        self.__balance = initial_balance   # 私有属性,外部不能直接访问

    def deposit(self, amount: float) -> bool:
        """存款:验证金额合法性后增加余额"""
        if amount > 0:
            self.__balance += amount
            print(f"✅ 存款成功!当前余额:{self.__balance:.2f}")
            return True
        print("❌ 存款失败:金额必须大于0")
        return False

    def withdraw(self, amount: float) -> bool:
        """取款:验证金额合法性并检查余额"""
        if 0 < amount <= self.__balance:
            self.__balance -= amount
            print(f"✅ 取款成功!当前余额:{self.__balance:.2f}")
            return True
        print(f"❌ 取款失败:金额无效或余额不足(当前:{self.__balance:.2f})")
        return False

    def get_balance(self) -> float:
        """对外提供的唯一余额查询接口"""
        return self.__balance

by only exposingdepositwithdrawandget_balance, we can ensure that the balance will not be tampered with by external code at will, and all changes will be legally checked.

3.2 Inheritance

Inheritance is an "is‑a" relationship in which subclasses automatically obtain the properties and methods of the parent class and can:

  • Override the method of the parent class;
  • Added subclass-specific attributes and methods.

Python supports multiple inheritance, but you need to be careful when using it to avoid the confusion caused by "diamond inheritance".

Inheritance example: Person → Student

class Person:
    """父类:通用的人类属性和方法"""
    def __init__(self, name: str, age: int):
        self.name = name
        self.age = age

    def introduce(self) -> str:
        return f"👋 大家好,我是{self.name},今年{self.age}岁。"

# Student 继承自 Person
class Student(Person):
    """子类:增加学号,重写自我介绍"""
    def __init__(self, name: str, age: int, student_id: str):
        super().__init__(name, age)   # 调用父类的初始化方法
        self.student_id = student_id

    def introduce(self) -> str:       # 重写父类方法
        # 通过 super() 复用父类的自我介绍
        return f"{super().introduce()} 🎓 我的学号是{self.student_id}。"

🔑 Keywordssuper(): Allows you to easily call the method of the parent class, whether during initialization or in a normal method.

3.3 Polymorphism

Polymorphism literally means "multiple forms", and the core idea is: Different objects can make their own responses to the same message (method call). Three prerequisites for achieving polymorphism:

  1. The parent class defines a public interface (which can be a common method or an abstract method);
  2. The subclass inherits the parent class and rewrites the interface;
  3. The caller only relies on the parent class type and does not care which subclass it is.

Polymorphic example: animal sounds

class Animal:
    """父类:定义 speak 公共接口"""
    def speak(self) -> str:
        raise NotImplementedError("Animal 的子类必须实现 speak 方法!")

class Dog(Animal):
    def speak(self) -> str:
        return "🐕 Woof! Woof!"

class Cat(Animal):
    def speak(self) -> str:
        return "🐱 Meow~ Meow~"

# 多态的使用:函数只接收 Animal 类型
def make_animal_speak(animal: Animal) -> None:
    print(animal.speak())

# 传入不同的子类对象,各自执行不同的 speak 逻辑
make_animal_speak(Dog())   # 输出:🐕 Woof! Woof!
make_animal_speak(Cat())   # 输出:🐱 Meow~ Meow~

4. Python OOP advanced-features

Python provides some syntactic sugar to make OOP code more concise and efficient.

4.1 Class methods and static methods

In addition to ordinary instance methods, Python has two special methods:

Method typeDecoratorFirst parameterTypical uses
Instance methodsNone (default)self(Instance itself)Manipulate instance properties
Class methods@classmethodcls(Class itself)Manipulate class attributes, factory methods
static method@staticmethodNo automatic passingUtility functions that are related to the class but do not require access to the class/instance
class Calculator:
    # 类属性:所有实例共享
    PI = 3.1415926535

    def __init__(self, value: float):
        self.value = value

    @classmethod
    def get_pi(cls) -> float:
        """类方法:获取 π 的值"""
        return cls.PI

    @classmethod
    def set_pi(cls, new_pi: float) -> None:
        """类方法:修改 π 的值(影响所有实例)"""
        cls.PI = new_pi

    @staticmethod
    def add(a: float, b: float) -> float:
        """静态方法:简单的加法,无需实例或类属性"""
        return a + b

4.2 Property Decorator@property

use@propertyMethod calls can be converted into syntax like accessing properties, which not only maintains encapsulation but also improves readability.

Example: radius and area of ​​a circle

class Circle:
    PI = 3.1415926535

    def __init__(self, radius: float):
        self._radius = radius   # 单下划线:约定“受保护”,建议不直接访问

    @property
    def radius(self) -> float:
        """让 radius 可以像属性一样读取"""
        return self._radius

    @radius.setter
    def radius(self, value: float) -> None:
        """设置 radius 时自动进行合法性检查"""
        if value <= 0:
            raise ValueError("❌ 半径必须是正数!")
        self._radius = value

    @property
    def area(self) -> float:
        """只读属性:访问时自动计算,无法外部赋值"""
        return self.PI * self._radius ** 2

Now you can use them like normal properties:circle.radiuscircle.area, while the interior remains protected.

4.3 Abstract Base Class (ABC)

The interface constraint of an ordinary parent class is to "report an error at runtime", while the Abstract Base Class (ABC) can detect errors during instantiation and force the subclass to implement the specified abstract method.

from abc import ABC, abstractmethod

class Shape(ABC):   # 必须继承 ABC
    """抽象基类:所有图形必须提供面积和周长的计算"""

    @abstractmethod
    def area(self) -> float:
        pass

    @abstractmethod
    def perimeter(self) -> float:
        pass

# 实现了所有抽象方法的子类才能实例化
class Rectangle(Shape):
    def __init__(self, width: float, height: float):
        self.width = width
        self.height = height

    def area(self) -> float:
        return self.width * self.height

    def perimeter(self) -> float:
        return 2 * (self.width + self.height)

ifRectangleIf an abstract method is omitted, Python will directly report an error, thus exposing the problem in advance.


5. Modern Python OOP Best Practices

After mastering the basic syntax of OOP, the following practices can help you write more robust and professional code.

  1. Prefer composition to inheritance Inheritance means "is one" (student → person), combination means "has one" (car → engine). The combination is less coupled and more flexible.

    class Engine:
        def start(self) -> None:
            print("🚗 引擎启动!")
    
    class Car:
        def __init__(self):
            self.engine = Engine()   # 组合:Car 持有 Engine 的实例
    
        def start(self) -> None:
            self.engine.start()
  2. Use data classes@dataclassSimplify entity classes (Python3.7+) it will automatically generate__init____repr____eq__and other common methods, allowing you to focus on the data itself.

    from dataclasses import dataclass
    
    @dataclass
    class Point:
        x: float
        y: float
        z: float = 0.0   # 支持默认值
  3. Always add type hints Type hints not only improve readability but also allow the IDE to provide smart completion and static checking.

    class Vector:
        def __init__(self, x: float, y: float) -> None:
            self.x = x
            self.y = y
    
        # 前向引用:类尚未完全定义时使用 'Vector' 字符串
        def add(self, other: 'Vector') -> 'Vector':
            return Vector(self.x + other.x, self.y + other.y)
  4. Follow SOLID design principles Here are the golden rules of large-scale project design (easy to understand):

  • S Single responsibility: A class does only one thing.
  • O Opening and closing principle: open to extensions, closed to modifications.
  • L Liskov replacement: Subclasses can seamlessly replace parent classes.
  • I Interface isolation: only provide the interfaces required by the caller.
  • D Dependency inversion: rely on abstract interfaces rather than concrete implementations.

6. Summary

oop is the cornerstone of modern software development, and Python provides powerful and flexible support for it. The keys to mastering OOP are:

  1. Clarify the relationship between classes (blueprints) and objects (instances);
  2. Make flexible use of the three major features of encapsulation, inheritance, and polymorphism;
  3. Make good use of Python’s unique syntactic sugar (such as@property@dataclass、ABC);
  4. Follow composition-first, type-hint, and SOLID principles in actual projects.

When you can naturally map real-world business models into object interactions, the code is no longer a cold collection of instructions, but a dynamic and collaborative widget. I hope this tutorial can give you a clear and practical understanding of Python OOP, and give you an extra "weapon" when coding.