> 技术文档 > Python 进阶详解:类与对象(Classes and Objects)—— 面向对象编程的核心

Python 进阶详解:类与对象(Classes and Objects)—— 面向对象编程的核心


一、引言:什么是面向对象编程?

面向对象编程(OOP, Object-Oriented Programming) 是一种以“对象”为核心的编程范式,它通过 类(Class)对象(Object) 来组织代码,支持 封装、继承、多态 三大核心特性。

Python 是一种完全支持 OOP 的语言,其语法简洁而强大,允许你用最少的代码实现复杂的功能。

核心概念:

  • 类(Class):创建对象的蓝图或模板,定义了对象的属性和行为。
  • 对象(Object):类的实例,拥有类中定义的属性和方法

✅ 使用 OOP 可以使代码更加 模块化、可复用、易于维护和扩展


二、定义类

1. 基本语法

class 类名: \"\"\"文档字符串(可选)\"\"\" def __init__(self, 参数列表): \"\"\"初始化方法(构造函数)\"\"\" # 初始化实例属性 def 方法名(self, 参数列表): \"\"\"普通方法\"\"\" # 方法体

2. 示例:一个简单的 Person

python深色版本class Person: \"\"\"描述一个人的基本信息\"\"\" def __init__(self, name, age): self.name = name # 实例属性 self.age = age # 实例属性 def greet(self): print(f\"你好,我叫 {self.name},今年 {self.age} 岁。\")

__init__ 是构造函数,用于初始化新创建的对象状态。
self 参数指向当前实例,必须作为第一个参数传递给所有实例方法


三、创建对象(实例化)

创建类的实例称为“实例化”。

person1 = Person(\"Alice\", 25)person1.greet() # 输出:你好,我叫 Alice,今年 25 岁。

📌 每次调用 Person(...) 都会创建一个新的对象,彼此独立。


四、类的属性与方法

1. 实例属性 vs 类属性

类型

特点

作用范围

实例属性

每个实例都有自己的一份副本

实例独有

类属性

所有实例共享同一份数据

类级别共享

实例属性示例:
class Dog: def __init__(self, name): self.name = name # 每只狗有自己的名字dog1 = Dog(\"旺财\")dog2 = Dog(\"小黑\")print(dog1.name) # 旺财print(dog2.name) # 小黑
类属性示例:
class Dog: species = \"Canis familiaris\" # 所有狗共享这个物种 def __init__(self, name): self.name = namedog1 = Dog(\"旺财\")dog2 = Dog(\"小黑\")print(Dog.species) # Canis familiarisprint(dog1.species) # Canis familiaris(通过实例访问)

✅ 类属性适合存储所有实例共有的信息(如配置、常量)。


2. 实例方法 vs 类方法 vs 静态方法

方法类型

装饰器

第一个参数

用途

实例方法

self(实例)

访问实例属性和方法

类方法

@classmethod

cls(类)

创建工厂方法、操作类属性

静态方法

@staticmethod

工具函数,逻辑上属于类但不依赖实例或类

示例:
class MyClass: class_var = \"我是类变量\" def instance_method(self): print(f\"实例方法,访问 name={self.name}\") @classmethod def class_method(cls): print(f\"类方法,类名为 {cls.__name__},类变量={cls.class_var}\") @staticmethod def static_method(): print(\"这是一个静态方法,与类和实例无关\")# 使用示例obj = MyClass()obj.name = \"test\"obj.instance_method() # 实例方法MyClass.class_method() # 类方法MyClass.static_method() # 静态方法

✅ 推荐使用类方法实现“替代构造函数”:

@classmethoddef from_string(cls, data): name, age = data.split(\'-\') return cls(name, int(age))

五、继承(Inheritance)

继承允许一个类(子类)从另一个类(父类)派生属性和方法,实现代码复用功能扩展

1. 基本语法

class 子类名(父类名): pass

2. 示例:继承自 PersonStudent

class Student(Person): def __init__(self, name, age, grade): super().__init__(name, age) # 调用父类构造函数 self.grade = grade  # 新增属性 def study(self): print(f\"{self.name} 正在学习,年级为 {self.grade}。\")

super() 是调用父类方法的标准方式,推荐使用。


3. 方法重写(Override)

子类可以重写父类的方法以提供特定实现。

class Student(Person): def greet(self): print(f\"你好,我是学生 {self.name},今年 {self.age} 岁,正在读 {self.grade} 年级。\")

✅ 保持接口一致,行为不同 —— 这正是多态的基础。


六、多态(Polymorphism)

多态意味着不同的类可以通过相同的接口调用,表现出不同的行为。

示例:动物叫声

class Animal: def speak(self): raise NotImplementedError(\"子类必须实现此方法\")class Dog(Animal): def speak(self): return \"汪汪!\"class Cat(Animal): def speak(self): return \"喵喵!\"# 多态函数def animal_sound(animal: Animal): print(animal.speak())# 测试dog = Dog()cat = Cat()animal_sound(dog) # 输出:汪汪!animal_sound(cat) # 输出:喵喵!

✅ 多态让代码更具灵活性和可扩展性,新增动物无需修改 animal_sound 函数。


七、封装(Encapsulation)

封装是将对象的内部状态隐藏起来,仅暴露有限的接口供外部访问,从而增强安全性和简化使用。

1. 使用私有属性和方法

在属性或方法名前加双下划线 __ 表示私有成员(名称改写机制)。

class BankAccount: def __init__(self, balance=0): self.__balance = balance # 私有属性 def deposit(self, amount): if amount > 0: self.__balance += amount print(f\"存款 {amount} 元\") else: print(\"金额必须大于0\") def withdraw(self, amount): if 0 < amount <= self.__balance: self.__balance -= amount print(f\"取款 {amount} 元\") else: print(\"余额不足或金额无效\") def get_balance(self): return self.__balance # 提供只读访问

⚠️ Python 没有严格的访问控制(如 Java 的 private),但 __ 会触发名称改写(_ClassName__attribute),起到“弱私有”作用。

✅ 推荐使用属性装饰器(@property)来控制访问:

@propertydef balance(self): return self.__balance@balance.setterdef balance(self, value): if value >= 0: self.__balance = value else: print(\"余额不能为负数\")

八、总结:类与对象的核心要点

关键点

说明

定义类

使用 class关键字,包含属性和方法

实例化

创建类的对象(实例)

属性

分为实例属性(每个对象独有)和类属性(共享)

方法

实例方法(self)、类方法(@classmethod, cls)、静态方法(@staticmethod

继承

支持代码复用和扩展,使用 super() 调用父类方法

多态

不同类通过相同接口表现不同行为,提升灵活性

封装

保护对象内部状态,仅暴露必要接口,推荐使用 @property


九、最佳实践与建议

建议

说明

✅ 优先使用组合而非继承

更灵活,避免复杂的继承链

✅ 遵循单一职责原则

一个类只负责一个功能

✅ 使用 @property 控制属性访问

安全且优雅

✅ 合理设计类的接口

对外暴露最少必要方法

✅ 文档化你的类

使用 docstring 说明用途和用法


十、动手练习

1. 创建一个 Rectangle 类,包含计算面积和周长的方法

class Rectangle: def __init__(self, width, height): self.width = width self.height = height def area(self): return self.width * self.height def perimeter(self): return 2 * (self.width + self.height)# 测试rect = Rectangle(4, 5)print(f\"面积:{rect.area()}\") # 20print(f\"周长:{rect.perimeter()}\") # 18

2. 设计一个 Shape 基类及两个子类 CircleSquare,实现多态行为

import mathclass Shape: def area(self): raise NotImplementedError(\"子类必须实现 area 方法\")class Circle(Shape): def __init__(self, radius): self.radius = radius def area(self): return math.pi * self.radius ** 2class Square(Shape): def __init__(self, side): self.side = side def area(self): return self.side ** 2# 多态测试shapes = [Circle(3), Square(4)]for shape in shapes: print(f\"面积:{shape.area():.2f}\")# 输出:# 面积:28.27# 面积:16.00

3. 编写一个简单的银行账户系统,应用封装原则

class BankAccount: def __init__(self, owner, initial_balance=0): self.owner = owner self.__balance = initial_balance def deposit(self, amount): if amount > 0: self.__balance += amount print(f\"✅ {self.owner} 存款 {amount} 元\") else: print(\"❌ 存款金额必须大于0\") def withdraw(self, amount): if 0 < amount <= self.__balance: self.__balance -= amount print(f\"✅ {self.owner} 取款 {amount} 元\") else: print(\"❌ 余额不足或金额无效\") @property def balance(self): return self.__balance# 测试acc = BankAccount(\"张三\", 100)acc.deposit(50)acc.withdraw(30)acc.withdraw(200) # 余额不足print(f\"当前余额:{acc.balance} 元\") # 120 元

🚀 学习建议

  1. 多实践:尝试设计自己的类模型(如图书管理系统、学生信息管理)。
  2. 理解三大特性:深入掌握封装、继承、多态的原理和应用场景。
  3. 阅读优秀代码:学习标准库(如 datetime, collections)中的 OOP 设计。
  4. 进阶学习
    • 抽象基类(abc.ABC
    • 特殊方法(__str__, __repr__, __eq__ 等)
    • 设计模式(工厂、单例、观察者等)