☰
面向对象编程(OOP)在 Python 中的实现——类、继承与特殊方法
2026/10/27 20:00:24 网站建设 项目流程

面向对象编程(OOP)在 Python 中的实现——类、继承与特殊方法

写给习惯 POJO、getter/setter 和 final class 的你
本文是《从 Java 到 Python:一位后端工程师的零基础学习之旅》系列的第五篇。

在 Java 中,OOP 是构建大型系统的基石:

  • 一切皆对象
  • 类必须显式定义字段、构造函数、访问器
  • 继承、封装、多态是三大支柱

而 Python 虽然也支持完整的面向对象编程,但它的态度更务实:

“如果一个功能可以用简单函数实现,就不要强行用类。”

但这并不意味着 Python 的 OOP 能力弱——恰恰相反,它更灵活、更动态,甚至能实现 Java 无法做到的行为(比如运行时修改类结构)。

今天,我们就从类定义开始,一步步对比 Java 与 Python 的 OOP 实现,并重点讲解那些让 Python 对象“活起来”的特殊方法(Magic Methods)。


一、类定义:无需 public,无需字段声明

Java(显式、静态):

public class Student { private String name; private int age; public Student(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } }

Python(简洁、动态):

# student.py class Student: def __init__(self, name: str, age: int): self.name = name self.age = age

调用:

s = Student("Alice", 20) print(s.name) # Alice s.age = 21 # 直接赋值,无需 setter

🔍 关键差异:

  • 无public/private访问控制(靠命名约定)
  • 无字段预先声明(属性在__init__中动态创建)
  • 无需 getter/setter(直接访问属性)

💡 Python 哲学:“我们都是 consenting adults.”
意思是:开发者知道自己在做什么,不需要语言强行限制访问。


二、封装:用命名约定代替 private

Java 用private隐藏内部状态,Python 用命名约定:

命名

含义

说明

name

公共属性

可自由访问

_name

“受保护”

约定:不应直接访问(类似 Java 的protected)

__name

“私有”

名称改写(name mangling),避免子类意外覆盖

class BankAccount: def __init__(self, balance: float): self._balance = balance # 约定为内部使用 self.__pin = "1234" # 名称改写为 _BankAccount__pin def deposit(self, amount: float): self._balance += amount def get_pin(self) -> str: return self.__pin

⚠️ 注意:__pin并非真正私有!仍可通过account._BankAccount__pin访问。
Python 选择信任开发者,而非强制隔离。


三、属性(Property):优雅的 getter/setter

虽然 Python 不需要 getter/setter,但当你需要在赋值时加校验逻辑,可以用@property:

class Student: def __init__(self, name: str, age: int): self.name = name self._age = age @property def age(self) -> int: return self._age @age.setter def age(self, value: int): if value < 0: raise ValueError("Age cannot be negative") self._age = value

使用:

s = Student("Bob", 18) s.age = 19 # 调用 setter print(s.age) # 调用 getter → 19 s.age = -5 # 抛出 ValueError

✅ 对外表现:s.age像普通属性
✅ 对内实现:可加入逻辑校验
💡 类似 Java 的@Data+ 自定义 setter,但更轻量


四、继承:更灵活的多继承

Java(单继承):

class Person { /* ... */ } class Student extends Person { /* ... */ }

Python(支持多继承):

class Person: def __init__(self, name: str): self.name = name class Learner: def study(self): print("Studying...") class Student(Person, Learner): # 同时继承两个类 pass s = Student("Alice") s.study() # Studying...

⚠️ 多继承需谨慎(方法解析顺序 MRO 可能复杂)
✅ 但配合 Mixin 模式,可实现强大的功能组合(类似 Java 的接口 default 方法)


五、特殊方法(Magic Methods):让对象“像原生类型一样工作”

这是 Python OOP 最强大的部分!
通过实现__xxx__方法,你可以让自定义对象支持+、len()、str()、in等操作。

1.__str__vs__repr__(≈toString())

class Student: def __init__(self, name: str, age: int): self.name = name self.age = age def __str__(self): return f"Student({self.name}, {self.age})" def __repr__(self): return f"Student(name='{self.name}', age={self.age})"

使用:

s = Student("Alice", 20) print(s) # Student(Alice, 20) → 调用 __str__ print([s]) # [Student(name='Alice', age=20)] → 调用 __repr__

✅__str__:给人看(日志、UI)
✅__repr__:给开发者看(调试、日志),应尽量可eval重建


2.__eq__(定义相等逻辑)

def __eq__(self, other): if not isinstance(other, Student): return False return self.name == other.name and self.age == other.age

现在s1 == s2会比较内容,而非内存地址(Java 需重写equals())。


3.__len__,__getitem__(让对象像列表)

class GradeBook: def __init__(self, grades: list[int]): self.grades = grades def __len__(self): return len(self.grades) def __getitem__(self, index): return self.grades[index]

使用:

book = GradeBook([90, 85, 95]) print(len(book)) # 3 print(book[0]) # 90 for g in book: # 支持 for 循环! print(g)

🌟 这就是 Python 的“协议”思想:不关心类型,只关心行为(Duck Typing)


六、数据类(dataclasses):告别样板代码

Java 开发者常抱怨 POJO 写起来冗长。
Python 3.7+ 提供@dataclass,自动生成__init__、__repr__、__eq__:

from dataclasses import dataclass @dataclass class Student: name: str age: int active: bool = True # 默认值

等价于手动写:

class Student: def __init__(self, name: str, age: int, active: bool = True): self.name = name self.age = age self.active = active def __repr__(self): ... def __eq__(self, other): ...

✅ 支持类型提示
✅ 自动支持==比较
✅ 可通过@dataclass(frozen=True)实现不可变对象(类似 Java 的record)


七、对比总结:Java OOP vs Python OOP

特性

Java

Python

类定义

必须 public,文件名匹配

任意命名,无需访问修饰符

字段

需预先声明

动态创建

封装

private强制隐藏

_/__命名约定

getter/setter

必须手动写或用 Lombok

直接访问,或用@property

继承

单继承 + 接口

支持多继承(谨慎使用)

相等性

重写equals()

实现__eq__

字符串表示

重写toString()

实现__str__/__repr__

数据类

record(Java 14+)或 Lombok

@dataclass(内置)

多态

通过接口/抽象类

通过 Duck Typing(“像鸭子就当鸭子”)


结语:OOP 不是目的,而是工具

Java 把 OOP 作为默认范式,而 Python 把 OOP 作为可选工具。
你可以用类构建复杂系统,也可以用函数组合解决简单问题。

真正重要的是:选择最清晰、最可维护的方式表达你的逻辑。

当你开始用__str__让日志更友好,用@property加入校验,用@dataclass消除样板代码,
你会感受到 Python OOP 的优雅——它不强迫你,但始终为你准备好更简洁的表达。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询