Skip to content

Python 面向对象编程

面向对象编程(Object-Oriented Programming,OOP)是一种编程范式,它将数据和操作数据的方法封装在一起,以对象的形式组织代码。Python 是一种面向对象的编程语言,本章节将详细介绍 Python 中的面向对象编程概念和实践。

面向对象编程的基本概念

什么是对象?

对象是现实世界中实体的抽象,它具有:

  • 属性:描述对象的特征(数据)
  • 方法:描述对象的行为(操作)

什么是类?

类是对象的蓝图或模板,它定义了对象的属性和方法。通过类可以创建多个具有相同结构的对象。

面向对象编程的核心特性

  1. 封装:将数据和方法封装在类中,隐藏内部实现细节
  2. 继承:子类可以继承父类的属性和方法,实现代码复用
  3. 多态:不同类的对象可以使用相同的接口,表现出不同的行为
  4. 抽象:提取共同特征,忽略非本质细节

类的定义和使用

定义类

python
# 定义一个简单的类
class Person:
    """人员类"""
    
    # 类属性
    species = "人类"
    
    # 初始化方法
    def __init__(self, name, age):
        """初始化方法"""
        # 实例属性
        self.name = name
        self.age = age
    
    # 实例方法
    def greet(self):
        """打招呼方法"""
        print(f"你好,我是{self.name},今年{self.age}岁。")
    
    # 实例方法
    def celebrate_birthday(self):
        """庆祝生日方法"""
        self.age += 1
        print(f"{self.name}生日快乐!现在{self.age}岁了。")

# 测试类
if __name__ == "__main__":
    # 创建对象
    person1 = Person("张三", 25)
    person2 = Person("李四", 30)
    
    # 访问类属性
    print(f"Person.species: {Person.species}")
    print(f"person1.species: {person1.species}")
    print(f"person2.species: {person2.species}")
    
    # 访问实例属性
    print(f"person1.name: {person1.name}")
    print(f"person1.age: {person1.age}")
    print(f"person2.name: {person2.name}")
    print(f"person2.age: {person2.age}")
    
    # 调用实例方法
    person1.greet()
    person2.greet()
    
    # 调用方法修改属性
    person1.celebrate_birthday()
    person2.celebrate_birthday()
    
    # 再次访问实例属性
    print(f"person1.age: {person1.age}")
    print(f"person2.age: {person2.age}")

类的命名规范

  • 类名:使用驼峰命名法(CamelCase),首字母大写
  • 属性名:使用小写字母,单词之间用下划线连接
  • 方法名:使用小写字母,单词之间用下划线连接
  • 私有属性/方法:使用双下划线开头(__attribute

实例属性和类属性

实例属性

实例属性是每个对象独有的属性,在 __init__ 方法中通过 self.attribute 定义。

python
class Student:
    """学生类"""
    
    def __init__(self, name, student_id):
        """初始化方法"""
        # 实例属性
        self.name = name
        self.student_id = student_id
        self.courses = []
    
    def add_course(self, course):
        """添加课程"""
        self.courses.append(course)
    
    def get_courses(self):
        """获取课程列表"""
        return self.courses

# 测试
student1 = Student("王五", "2023001")
student2 = Student("赵六", "2023002")

student1.add_course("数学")
student1.add_course("英语")
student2.add_course("物理")

print(f"{student1.name}的课程: {student1.get_courses()}")
print(f"{student2.name}的课程: {student2.get_courses()}")

类属性

类属性是所有对象共享的属性,在类定义中直接定义。

python
class Car:
    """汽车类"""
    
    # 类属性
    wheels = 4
    manufacturer = "通用汽车"
    
    def __init__(self, model, year):
        """初始化方法"""
        # 实例属性
        self.model = model
        self.year = year
    
    def get_info(self):
        """获取汽车信息"""
        return f"{self.year} {self.manufacturer} {self.model}{self.wheels}个轮子"

# 测试
car1 = Car("科鲁兹", 2023)
car2 = Car("迈锐宝", 2024)

print(f"car1.get_info(): {car1.get_info()}")
print(f"car2.get_info(): {car2.get_info()}")

# 修改类属性
Car.wheels = 6
print(f"修改类属性后,car1.get_info(): {car1.get_info()}")
print(f"修改类属性后,car2.get_info(): {car2.get_info()}")

# 修改实例属性不会影响类属性
car1.wheels = 8
print(f"修改car1实例属性后,car1.get_info(): {car1.get_info()}")
print(f"修改car1实例属性后,car2.get_info(): {car2.get_info()}")
print(f"修改car1实例属性后,Car.wheels: {Car.wheels}")

方法类型

实例方法

实例方法是最常用的方法类型,它接收 self 参数,表示调用该方法的对象。

python
class Dog:
    """狗类"""
    
    def __init__(self, name, breed):
        """初始化方法"""
        self.name = name
        self.breed = breed
    
    # 实例方法
    def bark(self):
        """狗叫"""
        print(f"{self.name} ({self.breed}) 汪汪汪!")
    
    def fetch(self, item):
        """取东西"""
        print(f"{self.name} 取回了 {item}!")

# 测试
dog = Dog("小黑", "拉布拉多")
dog.bark()
dog.fetch("球")

类方法

类方法使用 @classmethod 装饰器标记,接收 cls 参数,表示调用该方法的类。

python
class Employee:
    """员工类"""
    
    # 类属性
    company = "ABC公司"
    employee_count = 0
    
    def __init__(self, name, salary):
        """初始化方法"""
        self.name = name
        self.salary = salary
        Employee.employee_count += 1
    
    # 类方法
    @classmethod
    def get_company(cls):
        """获取公司名称"""
        return cls.company
    
    @classmethod
    def set_company(cls, new_company):
        """设置公司名称"""
        cls.company = new_company
    
    @classmethod
    def get_employee_count(cls):
        """获取员工数量"""
        return cls.employee_count

# 测试
print(f"公司名称: {Employee.get_company()}")
print(f"员工数量: {Employee.get_employee_count()}")

emp1 = Employee("张三", 5000)
emp2 = Employee("李四", 6000)

print(f"员工数量: {Employee.get_employee_count()}")
print(f"emp1的公司: {emp1.get_company()}")
print(f"emp2的公司: {emp2.get_company()}")

# 修改公司名称
Employee.set_company("XYZ公司")
print(f"新公司名称: {Employee.get_company()}")
print(f"emp1的公司: {emp1.get_company()}")
print(f"emp2的公司: {emp2.get_company()}")

静态方法

静态方法使用 @staticmethod 装饰器标记,不接收 selfcls 参数,它与类和实例都没有直接关联。

python
class Calculator:
    """计算器类"""
    
    # 静态方法
    @staticmethod
    def add(a, b):
        """加法"""
        return a + b
    
    @staticmethod
    def subtract(a, b):
        """减法"""
        return a - b
    
    @staticmethod
    def multiply(a, b):
        """乘法"""
        return a * b
    
    @staticmethod
    def divide(a, b):
        """除法"""
        if b == 0:
            raise ValueError("除数不能为零")
        return a / b

# 测试
# 直接通过类调用
print(f"3 + 5 = {Calculator.add(3, 5)}")
print(f"10 - 4 = {Calculator.subtract(10, 4)}")
print(f"6 * 7 = {Calculator.multiply(6, 7)}")
print(f"20 / 5 = {Calculator.divide(20, 5)}")

# 通过实例调用
calc = Calculator()
print(f"8 + 2 = {calc.add(8, 2)}")
print(f"15 - 7 = {calc.subtract(15, 7)}")

封装

封装是将数据和方法封装在类中,隐藏内部实现细节,只提供公共接口。

私有属性和方法

在 Python 中,使用双下划线开头的属性和方法被视为私有,外部不能直接访问。

python
class BankAccount:
    """银行账户类"""
    
    def __init__(self, account_holder, balance):
        """初始化方法"""
        self.account_holder = account_holder  # 公共属性
        self.__balance = balance  # 私有属性
    
    # 公共方法
    def deposit(self, amount):
        """存款"""
        if amount > 0:
            self.__balance += amount
            print(f"存款成功!存入 {amount} 元,当前余额: {self.__balance} 元")
        else:
            print("存款金额必须大于零!")
    
    def withdraw(self, amount):
        """取款"""
        if amount > 0:
            if amount <= self.__balance:
                self.__balance -= amount
                print(f"取款成功!取出 {amount} 元,当前余额: {self.__balance} 元")
            else:
                print("余额不足!")
        else:
            print("取款金额必须大于零!")
    
    def get_balance(self):
        """获取余额"""
        return self.__balance
    
    # 私有方法
    def __check_balance(self):
        """检查余额"""
        print(f"当前余额: {self.__balance} 元")

# 测试
account = BankAccount("张三", 1000)
print(f"账户持有人: {account.account_holder}")
print(f"当前余额: {account.get_balance()} 元")

# 尝试直接访问私有属性(会失败)
# print(account.__balance)  # 会抛出 AttributeError

# 尝试调用私有方法(会失败)
# account.__check_balance()  # 会抛出 AttributeError

# 通过公共方法操作
account.deposit(500)
account.withdraw(200)
account.withdraw(2000)  # 余额不足

# 注意:Python 的私有属性只是名称修饰,并非真正私有
# 可以通过 _类名__属性名 访问
print(f"通过名称修饰访问余额: {account._BankAccount__balance} 元")
account._BankAccount__check_balance()  # 调用私有方法

@property 装饰器

@property 装饰器用于将方法转换为属性,提供更优雅的访问方式。

python
class Circle:
    """圆形类"""
    
    def __init__(self, radius):
        """初始化方法"""
        self.__radius = radius
    
    @property
    def radius(self):
        """半径属性"""
        return self.__radius
    
    @radius.setter
    def radius(self, value):
        """设置半径"""
        if value > 0:
            self.__radius = value
        else:
            raise ValueError("半径必须大于零!")
    
    @property
    def area(self):
        """面积属性"""
        import math
        return math.pi * self.__radius ** 2
    
    @property
    def circumference(self):
        """周长属性"""
        import math
        return 2 * math.pi * self.__radius

# 测试
circle = Circle(5)
print(f"半径: {circle.radius}")
print(f"面积: {circle.area}")
print(f"周长: {circle.circumference}")

# 修改半径
circle.radius = 10
print(f"\n修改半径后:")
print(f"半径: {circle.radius}")
print(f"面积: {circle.area}")
print(f"周长: {circle.circumference}")

# 尝试设置负数半径
try:
    circle.radius = -5
except ValueError as e:
    print(f"\n错误: {e}")

# 注意:area 和 circumference 是只读属性,不能修改
# circle.area = 100  # 会抛出 AttributeError

继承

继承是子类可以继承父类的属性和方法,实现代码复用。

基本继承

python
# 父类
class Animal:
    """动物类"""
    
    def __init__(self, name):
        """初始化方法"""
        self.name = name
    
    def eat(self):
        """吃"""
        print(f"{self.name} 在吃东西")
    
    def sleep(self):
        """睡"""
        print(f"{self.name} 在睡觉")

# 子类
class Dog(Animal):
    """狗类"""
    
    def __init__(self, name, breed):
        """初始化方法"""
        # 调用父类的初始化方法
        super().__init__(name)
        self.breed = breed
    
    def bark(self):
        """狗叫"""
        print(f"{self.name} ({self.breed}) 在汪汪叫")
    
    # 重写父类方法
    def sleep(self):
        """睡"""
        print(f"{self.name} ({self.breed}) 在狗窝里睡觉")

# 子类
class Cat(Animal):
    """猫类"""
    
    def __init__(self, name, color):
        """初始化方法"""
        # 调用父类的初始化方法
        super().__init__(name)
        self.color = color
    
    def meow(self):
        """猫叫"""
        print(f"{self.name} ({self.color}) 在喵喵叫")
    
    # 重写父类方法
    def sleep(self):
        """睡"""
        print(f"{self.name} ({self.color}) 在沙发上睡觉")

# 测试
dog = Dog("小黑", "拉布拉多")
dog.eat()
dog.sleep()
dog.bark()

print()

cat = Cat("小白", "白色")
cat.eat()
cat.sleep()
cat.meow()

多重继承

Python 支持多重继承,一个子类可以继承多个父类。

python
# 父类1
class Flyable:
    """可飞行的"""
    
    def fly(self):
        """飞行"""
        print("正在飞行")

# 父类2
class Swimmable:
    """可游泳的"""
    
    def swim(self):
        """游泳"""
        print("正在游泳")

# 父类3
class Walkable:
    """可行走的"""
    
    def walk(self):
        """行走"""
        print("正在行走")

# 子类:继承多个父类
class Duck(Flyable, Swimmable, Walkable):
    """鸭子类"""
    
    def __init__(self, name):
        """初始化方法"""
        self.name = name
    
    def quack(self):
        """鸭叫"""
        print(f"{self.name} 在嘎嘎叫")

# 测试
duck = Duck("唐老鸭")
duck.quack()
duck.fly()
duck.swim()
duck.walk()

方法解析顺序(MRO)

当一个类继承多个父类时,Python 使用 C3 线性化算法来确定方法解析顺序。

python
# 父类1
class A:
    def method(self):
        print("A.method")

# 父类2
class B(A):
    def method(self):
        print("B.method")

# 父类3
class C(A):
    def method(self):
        print("C.method")

# 子类:继承 B 和 C
class D(B, C):
    pass

# 测试
print(f"D的方法解析顺序: {[cls.__name__ for cls in D.__mro__]}")
d = D()
d.method()  # 调用 B.method

# 另一个例子
class X:
    def method(self):
        print("X.method")

class Y:
    def method(self):
        print("Y.method")

class Z(X, Y):
    pass

class W(Y, X):
    pass

print(f"Z的方法解析顺序: {[cls.__name__ for cls in Z.__mro__]}")
z = Z()
z.method()  # 调用 X.method

print(f"W的方法解析顺序: {[cls.__name__ for cls in W.__mro__]}")
w = W()
w.method()  # 调用 Y.method

多态

多态是指不同类的对象可以使用相同的接口,表现出不同的行为。

基本多态

python
class Shape:
    """形状类"""
    
    def area(self):
        """计算面积"""
        pass
    
    def perimeter(self):
        """计算周长"""
        pass

class Rectangle(Shape):
    """矩形类"""
    
    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)

class Circle(Shape):
    """圆形类"""
    
    def __init__(self, radius):
        """初始化方法"""
        self.radius = radius
    
    def area(self):
        """计算面积"""
        import math
        return math.pi * self.radius ** 2
    
    def perimeter(self):
        """计算周长"""
        import math
        return 2 * math.pi * self.radius

# 多态函数
def print_shape_info(shape):
    """打印形状信息"""
    print(f"面积: {shape.area():.2f}")
    print(f"周长: {shape.perimeter():.2f}")

# 测试
rectangle = Rectangle(4, 5)
circle = Circle(3)

print("矩形:")
print_shape_info(rectangle)

print("\n圆形:")
print_shape_info(circle)

鸭子类型

Python 是一种动态类型语言,它使用鸭子类型:"如果它走路像鸭子,叫声像鸭子,那么它就是鸭子"。

python
class Duck:
    """鸭子类"""
    
    def quack(self):
        """鸭叫"""
        print("嘎嘎嘎")
    
    def fly(self):
        """飞行"""
        print("鸭子在飞")

class Person:
    """人类"""
    
    def quack(self):
        """模仿鸭叫"""
        print("人在模仿鸭叫:嘎嘎嘎")
    
    def fly(self):
        """模仿飞行"""
        print("人在模仿飞行")

# 多态函数
def duck_behavior(duck):
    """鸭子行为"""
    duck.quack()
    duck.fly()

# 测试
duck = Duck()
person = Person()

print("鸭子:")
duck_behavior(duck)

print("\n人:")
duck_behavior(person)

抽象类

抽象类是不能直接实例化的类,它定义了子类必须实现的方法。

使用 abc 模块创建抽象类

python
from abc import ABC, abstractmethod

class Animal(ABC):
    """动物抽象类"""
    
    def __init__(self, name):
        """初始化方法"""
        self.name = name
    
    @abstractmethod
    def make_sound(self):
        """发出声音"""
        pass
    
    @abstractmethod
    def move(self):
        """移动"""
        pass
    
    def eat(self):
        """吃"""
        print(f"{self.name} 在吃东西")

class Dog(Animal):
    """狗类"""
    
    def make_sound(self):
        """发出声音"""
        print(f"{self.name} 在汪汪叫")
    
    def move(self):
        """移动"""
        print(f"{self.name} 在奔跑")

class Cat(Animal):
    """猫类"""
    
    def make_sound(self):
        """发出声音"""
        print(f"{self.name} 在喵喵叫")
    
    def move(self):
        """移动"""
        print(f"{self.name} 在跳跃")

# 测试
# 不能直接实例化抽象类
# animal = Animal("动物")  # 会抛出 TypeError

dog = Dog("小黑")
dog.make_sound()
dog.move()
dog.eat()

print()

cat = Cat("小白")
cat.make_sound()
cat.move()
cat.eat()

特殊方法

Python 中有许多特殊方法(也称为魔术方法或双下划线方法),它们以双下划线开头和结尾,用于实现对象的特殊行为。

常用特殊方法

python
class Vector:
    """向量类"""
    
    def __init__(self, x, y):
        """初始化方法"""
        self.x = x
        self.y = y
    
    def __repr__(self):
        """表示方法"""
        return f"Vector({self.x}, {self.y})"
    
    def __str__(self):
        """字符串方法"""
        return f"({self.x}, {self.y})"
    
    def __add__(self, other):
        """加法"""
        if isinstance(other, Vector):
            return Vector(self.x + other.x, self.y + other.y)
        raise TypeError("只能与 Vector 类型相加")
    
    def __sub__(self, other):
        """减法"""
        if isinstance(other, Vector):
            return Vector(self.x - other.x, self.y - other.y)
        raise TypeError("只能与 Vector 类型相减")
    
    def __mul__(self, scalar):
        """乘法"""
        if isinstance(scalar, (int, float)):
            return Vector(self.x * scalar, self.y * scalar)
        raise TypeError("只能与数字类型相乘")
    
    def __rmul__(self, scalar):
        """右乘法"""
        return self * scalar
    
    def __eq__(self, other):
        """等于"""
        if isinstance(other, Vector):
            return self.x == other.x and self.y == other.y
        return False
    
    def __abs__(self):
        """绝对值"""
        import math
        return math.sqrt(self.x ** 2 + self.y ** 2)
    
    def __bool__(self):
        """布尔值"""
        return self.x != 0 or self.y != 0

# 测试
v1 = Vector(3, 4)
v2 = Vector(1, 2)

print(f"v1: {v1}")
print(f"v2: {v2}")
print(f"repr(v1): {repr(v1)}")
print(f"str(v1): {str(v1)}")

print(f"v1 + v2: {v1 + v2}")
print(f"v1 - v2: {v1 - v2}")
print(f"v1 * 2: {v1 * 2}")
print(f"2 * v1: {2 * v1}")
print(f"abs(v1): {abs(v1)}")
print(f"v1 == v2: {v1 == v2}")
print(f"v1 == Vector(3, 4): {v1 == Vector(3, 4)}")
print(f"bool(v1): {bool(v1)}")
print(f"bool(Vector(0, 0)): {bool(Vector(0, 0))}")

容器类型特殊方法

python
class CustomList:
    """自定义列表类"""
    
    def __init__(self, items=None):
        """初始化方法"""
        self.items = items if items else []
    
    def __repr__(self):
        """表示方法"""
        return f"CustomList({self.items})"
    
    def __len__(self):
        """长度"""
        return len(self.items)
    
    def __getitem__(self, index):
        """获取元素"""
        return self.items[index]
    
    def __setitem__(self, index, value):
        """设置元素"""
        self.items[index] = value
    
    def __delitem__(self, index):
        """删除元素"""
        del self.items[index]
    
    def __iter__(self):
        """迭代器"""
        return iter(self.items)
    
    def __contains__(self, item):
        """包含"""
        return item in self.items

# 测试
clist = CustomList([1, 2, 3, 4, 5])
print(f"clist: {clist}")
print(f"len(clist): {len(clist)}")
print(f"clist[0]: {clist[0]}")
print(f"clist[1:3]: {clist[1:3]}")

# 修改元素
clist[2] = 10
print(f"修改后 clist: {clist}")

# 删除元素
del clist[1]
print(f"删除后 clist: {clist}")

# 迭代
print("迭代 clist:")
for item in clist:
    print(item)

# 包含
print(f"3 在 clist 中: {3 in clist}")
print(f"10 在 clist 中: {10 in clist}")

面向对象编程的实际应用

示例 1:学生管理系统

python
class Student:
    """学生类"""
    
    def __init__(self, student_id, name, age, grade):
        """初始化方法"""
        self.student_id = student_id
        self.name = name
        self.age = age
        self.grade = grade
    
    def __repr__(self):
        """表示方法"""
        return f"Student({self.student_id}, '{self.name}', {self.age}, '{self.grade}')"
    
    def update_grade(self, new_grade):
        """更新年级"""
        self.grade = new_grade

class StudentManager:
    """学生管理类"""
    
    def __init__(self):
        """初始化方法"""
        self.students = []
    
    def add_student(self, student):
        """添加学生"""
        self.students.append(student)
        print(f"已添加学生: {student}")
    
    def remove_student(self, student_id):
        """删除学生"""
        for i, student in enumerate(self.students):
            if student.student_id == student_id:
                removed_student = self.students.pop(i)
                print(f"已删除学生: {removed_student}")
                return True
        print(f"未找到学号为 {student_id} 的学生")
        return False
    
    def find_student(self, student_id):
        """查找学生"""
        for student in self.students:
            if student.student_id == student_id:
                return student
        return None
    
    def list_students(self):
        """列出所有学生"""
        if not self.students:
            print("没有学生记录")
            return
        print("学生列表:")
        for student in self.students:
            print(student)

# 测试
manager = StudentManager()

# 添加学生
manager.add_student(Student(1, "张三", 18, "大一"))
manager.add_student(Student(2, "李四", 19, "大二"))
manager.add_student(Student(3, "王五", 20, "大三"))

print()

# 列出学生
manager.list_students()

print()

# 查找学生
student = manager.find_student(2)
if student:
    print(f"找到学生: {student}")
else:
    print("未找到学生")

print()

# 更新学生年级
if student:
    student.update_grade("大三")
    print(f"更新后学生: {student}")

print()

# 删除学生
manager.remove_student(1)

print()

# 列出学生
manager.list_students()

示例 2:银行账户系统

python
class Account:
    """账户基类"""
    
    def __init__(self, account_number, account_holder, balance=0):
        """初始化方法"""
        self.account_number = account_number
        self.account_holder = account_holder
        self._balance = balance
    
    def deposit(self, amount):
        """存款"""
        if amount > 0:
            self._balance += amount
            print(f"存款成功!存入 {amount} 元,当前余额: {self._balance} 元")
        else:
            print("存款金额必须大于零!")
    
    def withdraw(self, amount):
        """取款"""
        if amount > 0:
            if amount <= self._balance:
                self._balance -= amount
                print(f"取款成功!取出 {amount} 元,当前余额: {self._balance} 元")
                return True
            else:
                print("余额不足!")
                return False
        else:
            print("取款金额必须大于零!")
            return False
    
    def get_balance(self):
        """获取余额"""
        return self._balance
    
    def __repr__(self):
        """表示方法"""
        return f"{self.__class__.__name__}({self.account_number}, '{self.account_holder}', {self._balance})"

class SavingsAccount(Account):
    """储蓄账户"""
    
    def __init__(self, account_number, account_holder, balance=0, interest_rate=0.01):
        """初始化方法"""
        super().__init__(account_number, account_holder, balance)
        self.interest_rate = interest_rate
    
    def add_interest(self):
        """添加利息"""
        interest = self._balance * self.interest_rate
        self._balance += interest
        print(f"已添加利息: {interest:.2f} 元,当前余额: {self._balance} 元")

class CheckingAccount(Account):
    """支票账户"""
    
    def __init__(self, account_number, account_holder, balance=0, overdraft_limit=1000):
        """初始化方法"""
        super().__init__(account_number, account_holder, balance)
        self.overdraft_limit = overdraft_limit
    
    def withdraw(self, amount):
        """取款(支持透支)"""
        if amount > 0:
            if amount <= self._balance + self.overdraft_limit:
                self._balance -= amount
                print(f"取款成功!取出 {amount} 元,当前余额: {self._balance} 元")
                return True
            else:
                print(f"超出透支限额!最大可取: {self._balance + self.overdraft_limit} 元")
                return False
        else:
            print("取款金额必须大于零!")
            return False

# 测试
print("=== 储蓄账户测试 ===")
savings = SavingsAccount("SA001", "张三", 10000, 0.02)
print(f"初始状态: {savings}")
savings.deposit(5000)
savings.withdraw(2000)
savings.add_interest()
print(f"最终状态: {savings}")

print("\n=== 支票账户测试 ===")
checking = CheckingAccount("CA001", "李四", 5000, 2000)
print(f"初始状态: {checking}")
checking.deposit(3000)
checking.withdraw(9000)  # 超出余额但在透支限额内
checking.withdraw(2000)   # 超出透支限额
print(f"最终状态: {checking}")

面向对象编程的最佳实践

1. 单一职责原则

  • 一个类应该只负责一项职责:避免创建过大、功能过多的类
  • 职责分离:将不同的职责分配给不同的类

2. 开放封闭原则

  • 对扩展开放,对修改封闭:通过继承和多态实现扩展,而不是修改现有代码
  • 使用抽象类:定义接口,允许不同的实现

3. 里氏替换原则

  • 子类应该能够替换父类:子类应该保持父类的行为契约
  • 避免重写父类的非抽象方法:如果必须重写,确保行为兼容

4. 依赖倒置原则

  • 依赖抽象,不依赖具体实现:通过抽象类或接口进行依赖注入
  • 高层模块不应该依赖低层模块:两者都应该依赖抽象

5. 接口隔离原则

  • 接口应该小而专一:避免创建过大的接口
  • 客户端不应该依赖它不使用的接口:将大接口拆分为小接口

6. 组合优于继承

  • 优先使用组合:通过组合多个类来实现功能,而不是通过继承
  • 继承是一种强耦合:组合更加灵活,可以在运行时更改行为

7. 其他最佳实践

  • 命名规范:使用清晰、有意义的命名
  • 文档:为类和方法添加文档字符串
  • 异常处理:适当处理异常
  • 测试:为类和方法编写单元测试
  • 代码复用:通过继承、组合等方式复用代码
  • 性能考虑:避免不必要的计算和内存使用

总结

本章节介绍了 Python 中的面向对象编程,包括:

  1. 面向对象编程的基本概念:对象、类、封装、继承、多态、抽象
  2. 类的定义和使用:类的定义、实例化、属性和方法
  3. 属性类型:实例属性、类属性、私有属性
  4. 方法类型:实例方法、类方法、静态方法
  5. 封装:私有属性和方法、@property 装饰器
  6. 继承:基本继承、多重继承、方法解析顺序
  7. 多态:基本多态、鸭子类型
  8. 抽象类:使用 abc 模块创建抽象类
  9. 特殊方法:常用特殊方法、容器类型特殊方法
  10. 实际应用:学生管理系统、银行账户系统
  11. 最佳实践:单一职责原则、开放封闭原则、里氏替换原则、依赖倒置原则、接口隔离原则、组合优于继承

掌握面向对象编程,可以帮助你编写更加模块化、可维护、可扩展的代码。通过合理的类设计和使用面向对象的特性,可以提高代码的可读性和复用性,减少代码冗余,使代码更加优雅和高效。