第9天-面向对象编程

2023/6/15

# 第9天-Python面向对象编程

欢迎来到Python面向对象编程的世界!面向对象编程(Object-Oriented Programming,OOP)是一种强大的编程范式,它让我们能够创建更加模块化、可重用和易维护的代码。

# 什么是面向对象编程?

面向对象编程是一种编程范式,它将数据和操作数据的方法组织在一起,形成"对象"。这种方式更接近我们对现实世界的理解。

生活类比

  • 类(Class):像汽车的设计图纸,定义了汽车应该有什么属性和功能
  • 对象(Object):像根据图纸制造出的具体汽车
  • 属性(Attribute):像汽车的颜色、品牌、型号
  • 方法(Method):像汽车的启动、加速、刹车功能

# OOP的四大特性

  1. 封装(Encapsulation):将数据和方法包装在一起,隐藏内部实现细节
  2. 继承(Inheritance):子类可以继承父类的属性和方法
  3. 多态(Polymorphism):同一个方法在不同类中有不同的实现
  4. 抽象(Abstraction):隐藏复杂的实现细节,只暴露必要的接口

# 一、类和对象基础

# 1.1 定义类

# 定义一个简单的学生类
class Student:
    """学生类
    
    这个类用来表示一个学生,包含学生的基本信息和行为。
    """
    
    # 类变量(所有实例共享)
    school = "Python编程学院"
    student_count = 0
    
    def __init__(self, name, age, student_id):
        """构造方法(初始化方法)
        
        Args:
            name (str): 学生姓名
            age (int): 学生年龄
            student_id (str): 学号
        """
        # 实例变量(每个实例独有)
        self.name = name
        self.age = age
        self.student_id = student_id
        self.grades = {}  # 存储各科成绩
        self.is_enrolled = True
        
        # 每创建一个学生,计数器加1
        Student.student_count += 1
    
    def introduce(self):
        """自我介绍方法"""
        return f"大家好,我是{self.name},今年{self.age}岁,学号是{self.student_id}"
    
    def add_grade(self, subject, score):
        """添加成绩
        
        Args:
            subject (str): 科目名称
            score (float): 成绩分数
        """
        if 0 <= score <= 100:
            self.grades[subject] = score
            print(f"已为{self.name}添加{subject}成绩:{score}分")
        else:
            print("成绩必须在0-100之间")
    
    def get_average_grade(self):
        """计算平均成绩
        
        Returns:
            float: 平均成绩,如果没有成绩则返回0
        """
        if not self.grades:
            return 0
        return sum(self.grades.values()) / len(self.grades)
    
    def get_grade_level(self):
        """根据平均成绩获取等级
        
        Returns:
            str: 成绩等级
        """
        avg = self.get_average_grade()
        if avg >= 90:
            return "优秀"
        elif avg >= 80:
            return "良好"
        elif avg >= 70:
            return "中等"
        elif avg >= 60:
            return "及格"
        else:
            return "不及格"
    
    def enroll(self):
        """注册入学"""
        self.is_enrolled = True
        print(f"{self.name}已成功注册入学")
    
    def withdraw(self):
        """退学"""
        self.is_enrolled = False
        print(f"{self.name}已办理退学手续")
    
    @classmethod
    def get_student_count(cls):
        """类方法:获取学生总数
        
        Returns:
            int: 当前学生总数
        """
        return cls.student_count
    
    @classmethod
    def create_from_string(cls, student_info):
        """类方法:从字符串创建学生对象
        
        Args:
            student_info (str): 格式为 "姓名,年龄,学号" 的字符串
        
        Returns:
            Student: 新创建的学生对象
        """
        name, age, student_id = student_info.split(',')
        return cls(name.strip(), int(age.strip()), student_id.strip())
    
    @staticmethod
    def is_valid_student_id(student_id):
        """静态方法:验证学号格式
        
        Args:
            student_id (str): 学号
        
        Returns:
            bool: 学号是否有效
        """
        # 假设学号格式为:年份 + 4位数字
        return len(student_id) == 8 and student_id.isdigit()
    
    def __str__(self):
        """字符串表示方法"""
        status = "在读" if self.is_enrolled else "已退学"
        return f"学生({self.name}, {self.age}岁, {self.student_id}, {status})"
    
    def __repr__(self):
        """开发者友好的字符串表示"""
        return f"Student('{self.name}', {self.age}, '{self.student_id}')"
    
    def __eq__(self, other):
        """相等性比较"""
        if isinstance(other, Student):
            return self.student_id == other.student_id
        return False
    
    def __lt__(self, other):
        """小于比较(按平均成绩)"""
        if isinstance(other, Student):
            return self.get_average_grade() < other.get_average_grade()
        return NotImplemented

# 使用示例
print("=== 创建学生对象 ===")
# 创建学生对象
student1 = Student("张三", 20, "20230001")
student2 = Student("李四", 19, "20230002")
student3 = Student("王五", 21, "20230003")

print(student1)
print(student2)
print(student3)

print(f"\n当前学生总数:{Student.get_student_count()}")
print(f"学校名称:{Student.school}")

print("\n=== 学生自我介绍 ===")
print(student1.introduce())
print(student2.introduce())

print("\n=== 添加成绩 ===")
student1.add_grade("数学", 95)
student1.add_grade("英语", 87)
student1.add_grade("物理", 92)

student2.add_grade("数学", 78)
student2.add_grade("英语", 85)
student2.add_grade("物理", 80)

print(f"\n{student1.name}的平均成绩:{student1.get_average_grade():.2f}分,等级:{student1.get_grade_level()}")
print(f"{student2.name}的平均成绩:{student2.get_average_grade():.2f}分,等级:{student2.get_grade_level()}")

print("\n=== 使用类方法和静态方法 ===")
# 使用类方法创建学生
student4 = Student.create_from_string("赵六, 22, 20230004")
print(f"从字符串创建的学生:{student4}")

# 使用静态方法验证学号
print(f"学号20230001是否有效:{Student.is_valid_student_id('20230001')}")
print(f"学号123是否有效:{Student.is_valid_student_id('123')}")

print("\n=== 对象比较 ===")
print(f"student1 == student2: {student1 == student2}")
print(f"student1 < student2: {student1 < student2}")

# 1.2 属性访问控制

class BankAccount:
    """银行账户类 - 演示封装和属性访问控制"""
    
    def __init__(self, account_number, owner_name, initial_balance=0):
        self.account_number = account_number  # 公开属性
        self.owner_name = owner_name  # 公开属性
        self._balance = initial_balance  # 受保护属性(约定:单下划线)
        self.__pin = None  # 私有属性(双下划线)
        self.__transaction_history = []  # 私有属性
    
    def set_pin(self, pin):
        """设置PIN码"""
        if isinstance(pin, str) and len(pin) == 4 and pin.isdigit():
            self.__pin = pin
            print("PIN码设置成功")
        else:
            print("PIN码必须是4位数字")
    
    def verify_pin(self, pin):
        """验证PIN码"""
        return self.__pin == pin
    
    def deposit(self, amount, pin):
        """存款"""
        if not self.verify_pin(pin):
            print("PIN码错误")
            return False
        
        if amount > 0:
            self._balance += amount
            self.__add_transaction("存款", amount)
            print(f"存款成功,当前余额:{self._balance}元")
            return True
        else:
            print("存款金额必须大于0")
            return False
    
    def withdraw(self, amount, pin):
        """取款"""
        if not self.verify_pin(pin):
            print("PIN码错误")
            return False
        
        if amount > 0 and amount <= self._balance:
            self._balance -= amount
            self.__add_transaction("取款", -amount)
            print(f"取款成功,当前余额:{self._balance}元")
            return True
        else:
            print("取款金额无效或余额不足")
            return False
    
    def get_balance(self, pin):
        """查询余额"""
        if not self.verify_pin(pin):
            print("PIN码错误")
            return None
        return self._balance
    
    def get_transaction_history(self, pin):
        """获取交易历史"""
        if not self.verify_pin(pin):
            print("PIN码错误")
            return None
        return self.__transaction_history.copy()
    
    def __add_transaction(self, transaction_type, amount):
        """私有方法:添加交易记录"""
        from datetime import datetime
        transaction = {
            'type': transaction_type,
            'amount': amount,
            'timestamp': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
            'balance_after': self._balance
        }
        self.__transaction_history.append(transaction)
    
    def __str__(self):
        return f"银行账户({self.account_number}, {self.owner_name})"

# 使用示例
print("=== 银行账户示例 ===")
account = BankAccount("6222001234567890", "张三", 1000)
print(account)

# 设置PIN码
account.set_pin("1234")

# 存款
account.deposit(500, "1234")

# 取款
account.withdraw(200, "1234")

# 查询余额
balance = account.get_balance("1234")
print(f"当前余额:{balance}元")

# 查看交易历史
history = account.get_transaction_history("1234")
print("\n交易历史:")
for transaction in history:
    print(f"{transaction['timestamp']} - {transaction['type']}: {transaction['amount']}元, 余额: {transaction['balance_after']}元")

# 尝试直接访问私有属性(会失败)
print("\n=== 属性访问测试 ===")
print(f"公开属性 - 账户号码:{account.account_number}")
print(f"受保护属性 - 余额:{account._balance}")

# 尝试访问私有属性(Python会进行名称修饰)
try:
    print(account.__pin)  # 这会引发AttributeError
except AttributeError as e:
    print(f"无法直接访问私有属性:{e}")

# 实际上私有属性被修饰为 _ClassName__attributeName
print(f"通过名称修饰访问私有属性:{account._BankAccount__pin}")

# 二、继承

# 2.1 基本继承

# 基类(父类)
class Animal:
    """动物基类"""
    
    def __init__(self, name, species, age):
        self.name = name
        self.species = species
        self.age = age
        self.is_alive = True
    
    def eat(self, food):
        """吃东西"""
        print(f"{self.name}正在吃{food}")
    
    def sleep(self):
        """睡觉"""
        print(f"{self.name}正在睡觉")
    
    def make_sound(self):
        """发出声音(基类中的通用实现)"""
        print(f"{self.name}发出了声音")
    
    def get_info(self):
        """获取动物信息"""
        status = "活着" if self.is_alive else "已死亡"
        return f"{self.name}是一只{self.age}岁的{self.species},目前{status}"
    
    def __str__(self):
        return f"{self.species}({self.name})"

# 派生类(子类)
class Dog(Animal):
    """狗类 - 继承自Animal"""
    
    def __init__(self, name, breed, age, owner=None):
        # 调用父类的构造方法
        super().__init__(name, "狗", age)
        self.breed = breed  # 狗特有的属性
        self.owner = owner
        self.is_trained = False
    
    def make_sound(self):
        """重写父类方法 - 狗的叫声"""
        print(f"{self.name}汪汪叫")
    
    def wag_tail(self):
        """狗特有的方法 - 摇尾巴"""
        print(f"{self.name}开心地摇尾巴")
    
    def fetch(self, item):
        """狗特有的方法 - 捡东西"""
        print(f"{self.name}去捡{item}")
    
    def train(self, command):
        """训练狗"""
        print(f"正在训练{self.name}学习'{command}'命令")
        self.is_trained = True
    
    def get_info(self):
        """重写父类方法,添加狗特有信息"""
        base_info = super().get_info()
        breed_info = f",品种是{self.breed}"
        owner_info = f",主人是{self.owner}" if self.owner else ",还没有主人"
        training_info = f",{'已训练' if self.is_trained else '未训练'}"
        return base_info + breed_info + owner_info + training_info

class Cat(Animal):
    """猫类 - 继承自Animal"""
    
    def __init__(self, name, breed, age, is_indoor=True):
        super().__init__(name, "猫", age)
        self.breed = breed
        self.is_indoor = is_indoor
        self.lives_remaining = 9  # 猫有九条命
    
    def make_sound(self):
        """重写父类方法 - 猫的叫声"""
        print(f"{self.name}喵喵叫")
    
    def purr(self):
        """猫特有的方法 - 呼噜声"""
        print(f"{self.name}发出满足的呼噜声")
    
    def climb(self, target):
        """猫特有的方法 - 爬高"""
        print(f"{self.name}爬到了{target}上")
    
    def hunt(self, prey):
        """猫特有的方法 - 狩猎"""
        if not self.is_indoor:
            print(f"{self.name}正在狩猎{prey}")
        else:
            print(f"{self.name}是室内猫,不能狩猎")
    
    def lose_life(self):
        """失去一条命"""
        if self.lives_remaining > 0:
            self.lives_remaining -= 1
            print(f"{self.name}失去了一条命,还剩{self.lives_remaining}条命")
            if self.lives_remaining == 0:
                self.is_alive = False
                print(f"{self.name}用完了所有的命")
        else:
            print(f"{self.name}已经没有命了")

class Bird(Animal):
    """鸟类 - 继承自Animal"""
    
    def __init__(self, name, species, age, can_fly=True):
        super().__init__(name, species, age)
        self.can_fly = can_fly
        self.altitude = 0  # 当前高度
    
    def make_sound(self):
        """重写父类方法 - 鸟的叫声"""
        print(f"{self.name}啾啾叫")
    
    def fly(self, height):
        """鸟特有的方法 - 飞行"""
        if self.can_fly:
            self.altitude = height
            print(f"{self.name}飞到了{height}米高")
        else:
            print(f"{self.name}不会飞")
    
    def land(self):
        """降落"""
        if self.altitude > 0:
            print(f"{self.name}{self.altitude}米高降落到地面")
            self.altitude = 0
        else:
            print(f"{self.name}已经在地面上了")

# 使用示例
print("=== 继承示例 ===")

# 创建不同类型的动物
dog = Dog("旺财", "金毛", 3, "张三")
cat = Cat("咪咪", "波斯猫", 2, True)
bird = Bird("小黄", "金丝雀", 1, True)

animals = [dog, cat, bird]

print("=== 所有动物的基本信息 ===")
for animal in animals:
    print(animal.get_info())

print("\n=== 所有动物都会吃和睡 ===")
for animal in animals:
    animal.eat("食物")
    animal.sleep()

print("\n=== 多态:不同动物发出不同声音 ===")
for animal in animals:
    animal.make_sound()  # 每个子类都有自己的实现

print("\n=== 各种动物的特有行为 ===")
# 狗的特有行为
dog.wag_tail()
dog.fetch("球")
dog.train("坐下")

# 猫的特有行为
cat.purr()
cat.climb("书架")
cat.hunt("老鼠")
cat.lose_life()

# 鸟的特有行为
bird.fly(50)
bird.land()

print("\n=== 检查继承关系 ===")
print(f"dog是Animal的实例吗?{isinstance(dog, Animal)}")
print(f"dog是Dog的实例吗?{isinstance(dog, Dog)}")
print(f"dog是Cat的实例吗?{isinstance(dog, Cat)}")
print(f"Dog是Animal的子类吗?{issubclass(Dog, Animal)}")
print(f"Animal是Dog的子类吗?{issubclass(Animal, Dog)}")

# 2.2 多重继承

# 多重继承示例
class Flyable:
    """可飞行的混入类"""
    
    def __init__(self):
        self.max_altitude = 1000
        self.current_altitude = 0
    
    def take_off(self):
        """起飞"""
        if self.current_altitude == 0:
            self.current_altitude = 10
            print(f"{self.name}起飞了,当前高度:{self.current_altitude}米")
        else:
            print(f"{self.name}已经在飞行中")
    
    def fly_to_altitude(self, altitude):
        """飞到指定高度"""
        if altitude <= self.max_altitude:
            self.current_altitude = altitude
            print(f"{self.name}飞到了{altitude}米高")
        else:
            print(f"{self.name}无法飞到{altitude}米,最大高度是{self.max_altitude}米")
    
    def land(self):
        """降落"""
        if self.current_altitude > 0:
            print(f"{self.name}{self.current_altitude}米高降落")
            self.current_altitude = 0
        else:
            print(f"{self.name}已经在地面上")

class Swimmable:
    """可游泳的混入类"""
    
    def __init__(self):
        self.max_depth = 100
        self.current_depth = 0
    
    def dive(self, depth):
        """潜水"""
        if depth <= self.max_depth:
            self.current_depth = depth
            print(f"{self.name}潜水到{depth}米深")
        else:
            print(f"{self.name}无法潜到{depth}米,最大深度是{self.max_depth}米")
    
    def surface(self):
        """浮出水面"""
        if self.current_depth > 0:
            print(f"{self.name}{self.current_depth}米深浮出水面")
            self.current_depth = 0
        else:
            print(f"{self.name}已经在水面上")
    
    def swim(self, direction):
        """游泳"""
        print(f"{self.name}{direction}游泳")

class Duck(Animal, Flyable, Swimmable):
    """鸭子类 - 多重继承示例"""
    
    def __init__(self, name, age):
        # 调用所有父类的构造方法
        Animal.__init__(self, name, "鸭子", age)
        Flyable.__init__(self)
        Swimmable.__init__(self)
        
        # 重新设置鸭子的特定限制
        self.max_altitude = 500  # 鸭子飞不太高
        self.max_depth = 5  # 鸭子潜不太深
    
    def make_sound(self):
        """重写父类方法 - 鸭子的叫声"""
        print(f"{self.name}嘎嘎叫")
    
    def paddle(self):
        """鸭子特有的方法 - 划水"""
        print(f"{self.name}用脚掌划水")

class Penguin(Animal, Swimmable):
    """企鹅类 - 不会飞但会游泳"""
    
    def __init__(self, name, age):
        Animal.__init__(self, name, "企鹅", age)
        Swimmable.__init__(self)
        self.max_depth = 200  # 企鹅游泳很厉害
    
    def make_sound(self):
        """企鹅的叫声"""
        print(f"{self.name}发出企鹅特有的叫声")
    
    def slide_on_ice(self):
        """在冰上滑行"""
        print(f"{self.name}在冰上滑行")

# 使用示例
print("\n=== 多重继承示例 ===")

duck = Duck("唐老鸭", 2)
penguin = Penguin("企鹅先生", 3)

print("=== 鸭子的能力 ===")
print(duck.get_info())
duck.make_sound()

# 鸭子可以飞
duck.take_off()
duck.fly_to_altitude(200)
duck.land()

# 鸭子可以游泳
duck.swim("前方")
duck.dive(3)
duck.paddle()
duck.surface()

print("\n=== 企鹅的能力 ===")
print(penguin.get_info())
penguin.make_sound()

# 企鹅不能飞,但可以游泳
penguin.swim("深海")
penguin.dive(50)
penguin.slide_on_ice()
penguin.surface()

print("\n=== 方法解析顺序(MRO) ===")
print(f"Duck的MRO:{Duck.__mro__}")
print(f"Penguin的MRO:{Penguin.__mro__}")

# 三、多态

# 3.1 方法重写和多态

# 多态示例:图形类
class Shape:
    """图形基类"""
    
    def __init__(self, name):
        self.name = name
    
    def area(self):
        """计算面积 - 基类中的抽象方法"""
        raise NotImplementedError("子类必须实现area方法")
    
    def perimeter(self):
        """计算周长 - 基类中的抽象方法"""
        raise NotImplementedError("子类必须实现perimeter方法")
    
    def describe(self):
        """描述图形"""
        return f"这是一个{self.name},面积:{self.area():.2f},周长:{self.perimeter():.2f}"
    
    def __str__(self):
        return f"{self.name}(面积: {self.area():.2f})"

class Rectangle(Shape):
    """矩形类"""
    
    def __init__(self, width, height):
        super().__init__("矩形")
        self.width = width
        self.height = height
    
    def area(self):
        """矩形面积"""
        return self.width * self.height
    
    def perimeter(self):
        """矩形周长"""
        return 2 * (self.width + self.height)
    
    def is_square(self):
        """判断是否为正方形"""
        return self.width == self.height

class Circle(Shape):
    """圆形类"""
    
    def __init__(self, radius):
        super().__init__("圆形")
        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 diameter(self):
        """直径"""
        return 2 * self.radius

class Triangle(Shape):
    """三角形类"""
    
    def __init__(self, side1, side2, side3):
        super().__init__("三角形")
        self.side1 = side1
        self.side2 = side2
        self.side3 = side3
        
        # 验证是否能构成三角形
        if not self._is_valid_triangle():
            raise ValueError("无效的三角形边长")
    
    def _is_valid_triangle(self):
        """验证三角形的有效性"""
        return (self.side1 + self.side2 > self.side3 and
                self.side1 + self.side3 > self.side2 and
                self.side2 + self.side3 > self.side1)
    
    def area(self):
        """三角形面积(海伦公式)"""
        s = self.perimeter() / 2  # 半周长
        import math
        return math.sqrt(s * (s - self.side1) * (s - self.side2) * (s - self.side3))
    
    def perimeter(self):
        """三角形周长"""
        return self.side1 + self.side2 + self.side3
    
    def triangle_type(self):
        """判断三角形类型"""
        sides = sorted([self.side1, self.side2, self.side3])
        if sides[0] == sides[1] == sides[2]:
            return "等边三角形"
        elif sides[0] == sides[1] or sides[1] == sides[2]:
            return "等腰三角形"
        else:
            return "普通三角形"

# 多态函数
def calculate_total_area(shapes):
    """计算多个图形的总面积"""
    total = 0
    for shape in shapes:
        total += shape.area()  # 多态:每个图形都有自己的area实现
    return total

def print_shape_info(shapes):
    """打印图形信息"""
    for shape in shapes:
        print(shape.describe())  # 多态:调用各自的area和perimeter方法

def find_largest_shape(shapes):
    """找到面积最大的图形"""
    if not shapes:
        return None
    return max(shapes, key=lambda shape: shape.area())

# 使用示例
print("=== 多态示例 ===")

# 创建不同类型的图形
shapes = [
    Rectangle(5, 3),
    Circle(4),
    Triangle(3, 4, 5),
    Rectangle(2, 2),  # 正方形
    Circle(2.5)
]

print("=== 所有图形信息 ===")
print_shape_info(shapes)

print(f"\n=== 统计信息 ===")
print(f"图形总数:{len(shapes)}")
print(f"总面积:{calculate_total_area(shapes):.2f}")

largest = find_largest_shape(shapes)
print(f"面积最大的图形:{largest}")

print("\n=== 特定类型的操作 ===")
for shape in shapes:
    if isinstance(shape, Rectangle):
        if shape.is_square():
            print(f"{shape.name}是正方形,边长:{shape.width}")
        else:
            print(f"{shape.name}的长宽比:{shape.width/shape.height:.2f}")
    elif isinstance(shape, Circle):
        print(f"{shape.name}的直径:{shape.diameter():.2f}")
    elif isinstance(shape, Triangle):
        print(f"{shape.name}的类型:{shape.triangle_type()}")

# 演示多态的威力
print("\n=== 多态演示 ===")
def process_shape(shape):
    """处理任意图形 - 不需要知道具体类型"""
    print(f"处理{shape.name}:")
    print(f"  面积: {shape.area():.2f}")
    print(f"  周长: {shape.perimeter():.2f}")
    
    # 根据面积大小给出评价
    area = shape.area()
    if area > 50:
        print("  这是一个大图形")
    elif area > 20:
        print("  这是一个中等图形")
    else:
        print("  这是一个小图形")
    print()

for shape in shapes:
    process_shape(shape)  # 同一个函数处理不同类型的图形

# 3.2 抽象基类

from abc import ABC, abstractmethod

class Vehicle(ABC):
    """交通工具抽象基类"""
    
    def __init__(self, brand, model, year):
        self.brand = brand
        self.model = model
        self.year = year
        self.is_running = False
    
    @abstractmethod
    def start_engine(self):
        """启动引擎 - 抽象方法"""
        pass
    
    @abstractmethod
    def stop_engine(self):
        """停止引擎 - 抽象方法"""
        pass
    
    @abstractmethod
    def get_fuel_type(self):
        """获取燃料类型 - 抽象方法"""
        pass
    
    def get_info(self):
        """获取车辆信息 - 具体方法"""
        status = "运行中" if self.is_running else "停止"
        return f"{self.year}{self.brand} {self.model},当前状态:{status}"
    
    def honk(self):
        """鸣笛 - 具体方法"""
        print(f"{self.brand} {self.model}鸣笛:嘀嘀!")

class Car(Vehicle):
    """汽车类"""
    
    def __init__(self, brand, model, year, doors=4):
        super().__init__(brand, model, year)
        self.doors = doors
        self.fuel_level = 50  # 油量百分比
    
    def start_engine(self):
        """启动汽车引擎"""
        if not self.is_running:
            if self.fuel_level > 0:
                self.is_running = True
                print(f"{self.brand} {self.model}引擎启动成功")
            else:
                print(f"{self.brand} {self.model}没有燃料,无法启动")
        else:
            print(f"{self.brand} {self.model}引擎已经在运行")
    
    def stop_engine(self):
        """停止汽车引擎"""
        if self.is_running:
            self.is_running = False
            print(f"{self.brand} {self.model}引擎已停止")
        else:
            print(f"{self.brand} {self.model}引擎已经停止")
    
    def get_fuel_type(self):
        """获取燃料类型"""
        return "汽油"
    
    def refuel(self, amount):
        """加油"""
        self.fuel_level = min(100, self.fuel_level + amount)
        print(f"{self.brand} {self.model}加油完成,当前油量:{self.fuel_level}%")
    
    def drive(self, distance):
        """驾驶"""
        if self.is_running:
            fuel_consumed = distance * 0.1  # 假设每公里消耗0.1%的油
            if self.fuel_level >= fuel_consumed:
                self.fuel_level -= fuel_consumed
                print(f"{self.brand} {self.model}行驶了{distance}公里,剩余油量:{self.fuel_level:.1f}%")
            else:
                print(f"{self.brand} {self.model}燃料不足,无法行驶{distance}公里")
        else:
            print(f"{self.brand} {self.model}引擎未启动,无法行驶")

class ElectricCar(Vehicle):
    """电动汽车类"""
    
    def __init__(self, brand, model, year, battery_capacity=100):
        super().__init__(brand, model, year)
        self.battery_capacity = battery_capacity  # 电池容量(kWh)
        self.battery_level = 80  # 电量百分比
    
    def start_engine(self):
        """启动电动汽车"""
        if not self.is_running:
            if self.battery_level > 0:
                self.is_running = True
                print(f"{self.brand} {self.model}电动系统启动成功")
            else:
                print(f"{self.brand} {self.model}电池没电,无法启动")
        else:
            print(f"{self.brand} {self.model}电动系统已经在运行")
    
    def stop_engine(self):
        """停止电动汽车"""
        if self.is_running:
            self.is_running = False
            print(f"{self.brand} {self.model}电动系统已停止")
        else:
            print(f"{self.brand} {self.model}电动系统已经停止")
    
    def get_fuel_type(self):
        """获取燃料类型"""
        return "电力"
    
    def charge(self, hours):
        """充电"""
        charge_amount = hours * 10  # 假设每小时充电10%
        self.battery_level = min(100, self.battery_level + charge_amount)
        print(f"{self.brand} {self.model}充电{hours}小时,当前电量:{self.battery_level}%")
    
    def drive(self, distance):
        """驾驶电动汽车"""
        if self.is_running:
            battery_consumed = distance * 0.2  # 假设每公里消耗0.2%的电
            if self.battery_level >= battery_consumed:
                self.battery_level -= battery_consumed
                print(f"{self.brand} {self.model}行驶了{distance}公里,剩余电量:{self.battery_level:.1f}%")
            else:
                print(f"{self.brand} {self.model}电量不足,无法行驶{distance}公里")
        else:
            print(f"{self.brand} {self.model}电动系统未启动,无法行驶")

class Motorcycle(Vehicle):
    """摩托车类"""
    
    def __init__(self, brand, model, year, engine_size):
        super().__init__(brand, model, year)
        self.engine_size = engine_size  # 发动机排量
        self.fuel_level = 30
    
    def start_engine(self):
        """启动摩托车引擎"""
        if not self.is_running:
            if self.fuel_level > 0:
                self.is_running = True
                print(f"{self.brand} {self.model}摩托车引擎启动,轰鸣声响起")
            else:
                print(f"{self.brand} {self.model}没有燃料,无法启动")
        else:
            print(f"{self.brand} {self.model}引擎已经在运行")
    
    def stop_engine(self):
        """停止摩托车引擎"""
        if self.is_running:
            self.is_running = False
            print(f"{self.brand} {self.model}摩托车引擎已停止")
        else:
            print(f"{self.brand} {self.model}引擎已经停止")
    
    def get_fuel_type(self):
        """获取燃料类型"""
        return "汽油"
    
    def wheelie(self):
        """摩托车特技 - 翘头"""
        if self.is_running:
            print(f"{self.brand} {self.model}做了一个精彩的翘头动作!")
        else:
            print(f"{self.brand} {self.model}需要先启动引擎")

# 多态函数
def start_all_vehicles(vehicles):
    """启动所有车辆"""
    print("=== 启动所有车辆 ===")
    for vehicle in vehicles:
        vehicle.start_engine()

def show_vehicle_info(vehicles):
    """显示所有车辆信息"""
    print("=== 车辆信息 ===")
    for vehicle in vehicles:
        print(f"{vehicle.get_info()},燃料类型:{vehicle.get_fuel_type()}")

def honk_all(vehicles):
    """所有车辆鸣笛"""
    print("=== 集体鸣笛 ===")
    for vehicle in vehicles:
        vehicle.honk()

# 使用示例
print("=== 抽象基类和多态示例 ===")

# 创建不同类型的车辆
vehicles = [
    Car("丰田", "卡罗拉", 2022),
    ElectricCar("特斯拉", "Model 3", 2023, 75),
    Motorcycle("本田", "CBR600RR", 2021, 600)
]

# 显示车辆信息
show_vehicle_info(vehicles)

# 启动所有车辆
start_all_vehicles(vehicles)

# 集体鸣笛
honk_all(vehicles)

print("\n=== 特定操作 ===")
# 汽车加油和行驶
car = vehicles[0]
car.refuel(20)
car.drive(50)

# 电动汽车充电和行驶
electric_car = vehicles[1]
electric_car.charge(2)
electric_car.drive(30)

# 摩托车特技
motorcycle = vehicles[2]
motorcycle.wheelie()

# 尝试创建抽象基类的实例(会报错)
try:
    abstract_vehicle = Vehicle("测试", "测试", 2023)
except TypeError as e:
    print(f"\n无法创建抽象基类的实例:{e}")

# 四、特殊方法(魔术方法)

# 4.1 常用特殊方法

class Money:
    """货币类 - 演示特殊方法的使用"""
    
    def __init__(self, amount, currency="CNY"):
        self.amount = amount
        self.currency = currency
    
    def __str__(self):
        """用户友好的字符串表示"""
        currency_symbols = {
            "CNY": "¥",
            "USD": "$",
            "EUR": "€",
            "JPY": "¥"
        }
        symbol = currency_symbols.get(self.currency, self.currency)
        return f"{symbol}{self.amount:.2f}"
    
    def __repr__(self):
        """开发者友好的字符串表示"""
        return f"Money({self.amount}, '{self.currency}')"
    
    def __add__(self, other):
        """加法运算"""
        if isinstance(other, Money):
            if self.currency == other.currency:
                return Money(self.amount + other.amount, self.currency)
            else:
                raise ValueError(f"不能将{self.currency}{other.currency}直接相加")
        elif isinstance(other, (int, float)):
            return Money(self.amount + other, self.currency)
        else:
            return NotImplemented
    
    def __radd__(self, other):
        """右加法运算(当左操作数不支持加法时)"""
        return self.__add__(other)
    
    def __sub__(self, other):
        """减法运算"""
        if isinstance(other, Money):
            if self.currency == other.currency:
                return Money(self.amount - other.amount, self.currency)
            else:
                raise ValueError(f"不能将{self.currency}{other.currency}直接相减")
        elif isinstance(other, (int, float)):
            return Money(self.amount - other, self.currency)
        else:
            return NotImplemented
    
    def __mul__(self, other):
        """乘法运算"""
        if isinstance(other, (int, float)):
            return Money(self.amount * other, self.currency)
        else:
            return NotImplemented
    
    def __rmul__(self, other):
        """右乘法运算"""
        return self.__mul__(other)
    
    def __truediv__(self, other):
        """除法运算"""
        if isinstance(other, (int, float)):
            if other != 0:
                return Money(self.amount / other, self.currency)
            else:
                raise ZeroDivisionError("不能除以零")
        else:
            return NotImplemented
    
    def __eq__(self, other):
        """相等比较"""
        if isinstance(other, Money):
            return self.amount == other.amount and self.currency == other.currency
        return False
    
    def __lt__(self, other):
        """小于比较"""
        if isinstance(other, Money):
            if self.currency == other.currency:
                return self.amount < other.amount
            else:
                raise ValueError(f"不能比较{self.currency}{other.currency}")
        return NotImplemented
    
    def __le__(self, other):
        """小于等于比较"""
        return self == other or self < other
    
    def __gt__(self, other):
        """大于比较"""
        if isinstance(other, Money):
            if self.currency == other.currency:
                return self.amount > other.amount
            else:
                raise ValueError(f"不能比较{self.currency}{other.currency}")
        return NotImplemented
    
    def __ge__(self, other):
        """大于等于比较"""
        return self == other or self > other
    
    def __hash__(self):
        """哈希值(使对象可以用作字典键或集合元素)"""
        return hash((self.amount, self.currency))
    
    def __bool__(self):
        """布尔值转换"""
        return self.amount != 0
    
    def __abs__(self):
        """绝对值"""
        return Money(abs(self.amount), self.currency)
    
    def __neg__(self):
        """负数"""
        return Money(-self.amount, self.currency)
    
    def __round__(self, ndigits=2):
        """四舍五入"""
        return Money(round(self.amount, ndigits), self.currency)

class BankAccount:
    """银行账户类 - 演示容器特殊方法"""
    
    def __init__(self, owner, initial_balance=0):
        self.owner = owner
        self.balance = Money(initial_balance)
        self.transactions = []  # 交易记录
    
    def deposit(self, amount):
        """存款"""
        if isinstance(amount, (int, float)):
            amount = Money(amount)
        self.balance += amount
        self.transactions.append(f"存款 {amount}")
    
    def withdraw(self, amount):
        """取款"""
        if isinstance(amount, (int, float)):
            amount = Money(amount)
        if amount <= self.balance:
            self.balance -= amount
            self.transactions.append(f"取款 {amount}")
        else:
            raise ValueError("余额不足")
    
    def __len__(self):
        """返回交易记录数量"""
        return len(self.transactions)
    
    def __getitem__(self, index):
        """通过索引获取交易记录"""
        return self.transactions[index]
    
    def __setitem__(self, index, value):
        """通过索引设置交易记录"""
        self.transactions[index] = value
    
    def __delitem__(self, index):
        """通过索引删除交易记录"""
        del self.transactions[index]
    
    def __contains__(self, item):
        """检查是否包含某个交易记录"""
        return item in self.transactions
    
    def __iter__(self):
        """使对象可迭代"""
        return iter(self.transactions)
    
    def __str__(self):
        return f"账户所有者:{self.owner},余额:{self.balance}"
    
    def __repr__(self):
        return f"BankAccount('{self.owner}', {self.balance.amount})"

# 使用示例
print("=== 特殊方法示例 ===")

# 创建货币对象
money1 = Money(100, "CNY")
money2 = Money(50, "CNY")
money3 = Money(75, "USD")

print("=== 基本操作 ===")
print(f"money1: {money1}")
print(f"money2: {money2}")
print(f"money3: {money3}")
print(f"repr(money1): {repr(money1)}")

print("\n=== 算术运算 ===")
print(f"money1 + money2 = {money1 + money2}")
print(f"money1 - money2 = {money1 - money2}")
print(f"money1 * 2 = {money1 * 2}")
print(f"3 * money2 = {3 * money2}")
print(f"money1 / 4 = {money1 / 4}")
print(f"money1 + 25 = {money1 + 25}")

print("\n=== 比较运算 ===")
print(f"money1 == money2: {money1 == money2}")
print(f"money1 > money2: {money1 > money2}")
print(f"money1 < money2: {money1 < money2}")

print("\n=== 其他运算 ===")
print(f"abs(Money(-50)): {abs(Money(-50))}")
print(f"-money1: {-money1}")
print(f"round(Money(123.456)): {round(Money(123.456))}")
print(f"bool(Money(0)): {bool(Money(0))}")
print(f"bool(money1): {bool(money1)}")

print("\n=== 银行账户示例 ===")
account = BankAccount("张三", 1000)
print(account)

# 进行一些交易
account.deposit(500)
account.withdraw(200)
account.deposit(Money(300))

print(f"\n交易记录数量:{len(account)}")
print("所有交易记录:")
for i, transaction in enumerate(account):
    print(f"{i}: {transaction}")

print(f"\n第一笔交易:{account[0]}")
print(f"最后一笔交易:{account[-1]}")
print(f"是否包含'存款 ¥500.00':{'存款 ¥500.00' in account}")

# 货币对象可以用作字典键
print("\n=== 货币作为字典键 ===")
portfolio = {
    Money(1000, "CNY"): "人民币储蓄",
    Money(500, "USD"): "美元投资",
    Money(200, "EUR"): "欧元基金"
}

for currency, description in portfolio.items():
    print(f"{currency}: {description}")

# 尝试不同货币的运算(会报错)
try:
    result = money1 + money3  # CNY + USD
except ValueError as e:
    print(f"\n货币运算错误:{e}")

# 4.2 上下文管理器

class FileManager:
    """文件管理器 - 演示上下文管理器"""
    
    def __init__(self, filename, mode='r'):
        self.filename = filename
        self.mode = mode
        self.file = None
    
    def __enter__(self):
        """进入上下文时调用"""
        print(f"打开文件:{self.filename}")
        self.file = open(self.filename, self.mode)
        return self.file
    
    def __exit__(self, exc_type, exc_value, traceback):
        """退出上下文时调用"""
        if self.file:
            print(f"关闭文件:{self.filename}")
            self.file.close()
        
        # 处理异常
        if exc_type is not None:
            print(f"发生异常:{exc_type.__name__}: {exc_value}")
            return False  # 不抑制异常
        return True

class DatabaseConnection:
    """数据库连接 - 另一个上下文管理器示例"""
    
    def __init__(self, host, database):
        self.host = host
        self.database = database
        self.connection = None
    
    def __enter__(self):
        """建立数据库连接"""
        print(f"连接到数据库:{self.host}/{self.database}")
        # 这里模拟数据库连接
        self.connection = f"Connection to {self.database}"
        return self.connection
    
    def __exit__(self, exc_type, exc_value, traceback):
        """关闭数据库连接"""
        if self.connection:
            print(f"关闭数据库连接:{self.database}")
            self.connection = None
        return False

# 使用示例
print("\n=== 上下文管理器示例 ===")

# 使用自定义文件管理器
try:
    with FileManager("test.txt", "w") as f:
        f.write("Hello, World!")
        f.write("\nPython面向对象编程")
except FileNotFoundError:
    print("文件操作完成(文件可能不存在,这是正常的)")

# 使用数据库连接管理器
with DatabaseConnection("localhost", "myapp") as conn:
    print(f"使用连接:{conn}")
    # 模拟数据库操作
    print("执行SQL查询...")

print("连接已自动关闭")

# 五、属性装饰器

# 5.1 @property装饰器

class Temperature:
    """温度类 - 演示属性装饰器的使用"""
    
    def __init__(self, celsius=0):
        self._celsius = celsius
    
    @property
    def celsius(self):
        """获取摄氏温度"""
        return self._celsius
    
    @celsius.setter
    def celsius(self, value):
        """设置摄氏温度"""
        if value < -273.15:
            raise ValueError("温度不能低于绝对零度(-273.15°C)")
        self._celsius = value
    
    @property
    def fahrenheit(self):
        """获取华氏温度"""
        return self._celsius * 9/5 + 32
    
    @fahrenheit.setter
    def fahrenheit(self, value):
        """设置华氏温度"""
        celsius = (value - 32) * 5/9
        if celsius < -273.15:
            raise ValueError("温度不能低于绝对零度")
        self._celsius = celsius
    
    @property
    def kelvin(self):
        """获取开尔文温度"""
        return self._celsius + 273.15
    
    @kelvin.setter
    def kelvin(self, value):
        """设置开尔文温度"""
        if value < 0:
            raise ValueError("开尔文温度不能为负数")
        self._celsius = value - 273.15
    
    def __str__(self):
        return f"{self._celsius:.2f}°C ({self.fahrenheit:.2f}°F, {self.kelvin:.2f}K)"

class Circle:
    """圆形类 - 演示只读属性"""
    
    def __init__(self, radius):
        self._radius = radius
    
    @property
    def radius(self):
        """半径(只读)"""
        return self._radius
    
    @property
    def diameter(self):
        """直径(计算属性)"""
        return self._radius * 2
    
    @property
    def area(self):
        """面积(计算属性)"""
        import math
        return math.pi * self._radius ** 2
    
    @property
    def circumference(self):
        """周长(计算属性)"""
        import math
        return 2 * math.pi * self._radius
    
    def __str__(self):
        return f"圆形(半径: {self.radius}, 直径: {self.diameter:.2f}, 面积: {self.area:.2f}, 周长: {self.circumference:.2f})"

class Person:
    """人员类 - 演示属性验证"""
    
    def __init__(self, name, age, email):
        self.name = name
        self.age = age
        self.email = email
    
    @property
    def name(self):
        return self._name
    
    @name.setter
    def name(self, value):
        if not isinstance(value, str) or len(value.strip()) == 0:
            raise ValueError("姓名必须是非空字符串")
        self._name = value.strip()
    
    @property
    def age(self):
        return self._age
    
    @age.setter
    def age(self, value):
        if not isinstance(value, int) or value < 0 or value > 150:
            raise ValueError("年龄必须是0-150之间的整数")
        self._age = value
    
    @property
    def email(self):
        return self._email
    
    @email.setter
    def email(self, value):
        if not isinstance(value, str) or '@' not in value:
            raise ValueError("邮箱格式不正确")
        self._email = value.lower()
    
    @property
    def is_adult(self):
        """是否成年(只读属性)"""
        return self._age >= 18
    
    @property
    def age_group(self):
        """年龄组(只读属性)"""
        if self._age < 13:
            return "儿童"
        elif self._age < 18:
            return "青少年"
        elif self._age < 60:
            return "成年人"
        else:
            return "老年人"
    
    def __str__(self):
        return f"{self.name}({self.age}岁, {self.email}, {self.age_group})"

# 使用示例
print("=== 属性装饰器示例 ===")

# 温度转换
print("=== 温度转换 ===")
temp = Temperature(25)
print(f"初始温度:{temp}")

# 设置不同单位的温度
temp.fahrenheit = 100
print(f"设置华氏100度后:{temp}")

temp.kelvin = 300
print(f"设置开尔文300度后:{temp}")

# 尝试设置无效温度
try:
    temp.celsius = -300
except ValueError as e:
    print(f"温度设置错误:{e}")

# 圆形计算属性
print("\n=== 圆形计算属性 ===")
circle = Circle(5)
print(circle)

# 人员属性验证
print("\n=== 人员属性验证 ===")
try:
    person = Person("张三", 25, "zhangsan@example.com")
    print(person)
    print(f"是否成年:{person.is_adult}")
    
    # 修改属性
    person.age = 17
    print(f"修改年龄后:{person}")
    print(f"是否成年:{person.is_adult}")
    
    # 尝试设置无效邮箱
    person.email = "invalid-email"
except ValueError as e:
    print(f"属性设置错误:{e}")

# 六、实战练习

# 6.1 图书管理系统

from datetime import datetime, timedelta

class Book:
    """图书类"""
    
    def __init__(self, isbn, title, author, publisher, price, total_copies=1):
        self.isbn = isbn
        self.title = title
        self.author = author
        self.publisher = publisher
        self.price = price
        self.total_copies = total_copies
        self.available_copies = total_copies
        self.borrowed_copies = 0
    
    def borrow(self):
        """借书"""
        if self.available_copies > 0:
            self.available_copies -= 1
            self.borrowed_copies += 1
            return True
        return False
    
    def return_book(self):
        """还书"""
        if self.borrowed_copies > 0:
            self.available_copies += 1
            self.borrowed_copies -= 1
            return True
        return False
    
    @property
    def is_available(self):
        """是否有可借阅的副本"""
        return self.available_copies > 0
    
    def __str__(self):
        return f"《{self.title}》- {self.author} (可借: {self.available_copies}/{self.total_copies})"
    
    def __repr__(self):
        return f"Book('{self.isbn}', '{self.title}', '{self.author}')"

class Member:
    """会员类"""
    
    def __init__(self, member_id, name, phone, email):
        self.member_id = member_id
        self.name = name
        self.phone = phone
        self.email = email
        self.borrowed_books = []  # 当前借阅的书籍
        self.borrow_history = []  # 借阅历史
        self.join_date = datetime.now()
    
    def can_borrow(self, max_books=5):
        """检查是否可以借书"""
        return len(self.borrowed_books) < max_books
    
    def borrow_book(self, book, due_days=30):
        """借书"""
        if not self.can_borrow():
            return False, "已达到最大借书数量"
        
        if not book.is_available:
            return False, "图书不可借阅"
        
        if book.borrow():
            borrow_record = {
                'book': book,
                'borrow_date': datetime.now(),
                'due_date': datetime.now() + timedelta(days=due_days),
                'returned': False
            }
            self.borrowed_books.append(borrow_record)
            self.borrow_history.append(borrow_record)
            return True, "借书成功"
        
        return False, "借书失败"
    
    def return_book(self, book):
        """还书"""
        for record in self.borrowed_books:
            if record['book'] == book and not record['returned']:
                record['returned'] = True
                record['return_date'] = datetime.now()
                self.borrowed_books.remove(record)
                book.return_book()
                return True, "还书成功"
        
        return False, "未找到借阅记录"
    
    def get_overdue_books(self):
        """获取逾期图书"""
        overdue = []
        current_time = datetime.now()
        for record in self.borrowed_books:
            if current_time > record['due_date']:
                overdue.append(record)
        return overdue
    
    def __str__(self):
        return f"会员: {self.name} (ID: {self.member_id}, 当前借阅: {len(self.borrowed_books)}本)"

class Library:
    """图书馆类"""
    
    def __init__(self, name):
        self.name = name
        self.books = {}  # ISBN -> Book
        self.members = {}  # member_id -> Member
        self.next_member_id = 1
    
    def add_book(self, book):
        """添加图书"""
        if book.isbn in self.books:
            # 如果图书已存在,增加副本数
            existing_book = self.books[book.isbn]
            existing_book.total_copies += book.total_copies
            existing_book.available_copies += book.available_copies
        else:
            self.books[book.isbn] = book
        print(f"添加图书成功:{book}")
    
    def register_member(self, name, phone, email):
        """注册会员"""
        member_id = f"M{self.next_member_id:04d}"
        member = Member(member_id, name, phone, email)
        self.members[member_id] = member
        self.next_member_id += 1
        print(f"会员注册成功:{member}")
        return member
    
    def search_books(self, keyword):
        """搜索图书"""
        results = []
        keyword = keyword.lower()
        for book in self.books.values():
            if (keyword in book.title.lower() or 
                keyword in book.author.lower() or 
                keyword in book.publisher.lower()):
                results.append(book)
        return results
    
    def borrow_book(self, member_id, isbn):
        """借书"""
        if member_id not in self.members:
            return False, "会员不存在"
        
        if isbn not in self.books:
            return False, "图书不存在"
        
        member = self.members[member_id]
        book = self.books[isbn]
        
        return member.borrow_book(book)
    
    def return_book(self, member_id, isbn):
        """还书"""
        if member_id not in self.members:
            return False, "会员不存在"
        
        if isbn not in self.books:
            return False, "图书不存在"
        
        member = self.members[member_id]
        book = self.books[isbn]
        
        return member.return_book(book)
    
    def get_overdue_report(self):
        """获取逾期报告"""
        overdue_info = []
        for member in self.members.values():
            overdue_books = member.get_overdue_books()
            if overdue_books:
                overdue_info.append((member, overdue_books))
        return overdue_info
    
    def get_statistics(self):
        """获取统计信息"""
        total_books = sum(book.total_copies for book in self.books.values())
        available_books = sum(book.available_copies for book in self.books.values())
        borrowed_books = total_books - available_books
        
        return {
            'total_books': total_books,
            'available_books': available_books,
            'borrowed_books': borrowed_books,
            'total_members': len(self.members),
            'unique_titles': len(self.books)
        }
    
    def __str__(self):
        stats = self.get_statistics()
        return f"{self.name} - 图书: {stats['unique_titles']}种/{stats['total_books']}本, 会员: {stats['total_members']}人"

# 使用示例
print("\n=== 图书管理系统示例 ===")

# 创建图书馆
library = Library("Python学习图书馆")

# 添加图书
books_data = [
    ("978-0-123456-78-9", "Python编程:从入门到实践", "埃里克·马瑟斯", "人民邮电出版社", 89.0, 3),
    ("978-0-987654-32-1", "流畅的Python", "Luciano Ramalho", "O'Reilly", 139.0, 2),
    ("978-0-111111-11-1", "Python核心编程", "Wesley Chun", "机械工业出版社", 99.0, 2),
    ("978-0-222222-22-2", "Python数据分析", "Wes McKinney", "机械工业出版社", 119.0, 1)
]

for isbn, title, author, publisher, price, copies in books_data:
    book = Book(isbn, title, author, publisher, price, copies)
    library.add_book(book)

print(f"\n{library}")

# 注册会员
members = [
    library.register_member("张三", "13800138001", "zhangsan@example.com"),
    library.register_member("李四", "13800138002", "lisi@example.com"),
    library.register_member("王五", "13800138003", "wangwu@example.com")
]

# 搜索图书
print("\n=== 搜索图书 ===")
search_results = library.search_books("Python")
print(f"搜索'Python'的结果:")
for book in search_results:
    print(f"  {book}")

# 借书操作
print("\n=== 借书操作 ===")
borrow_operations = [
    ("M0001", "978-0-123456-78-9"),
    ("M0001", "978-0-987654-32-1"),
    ("M0002", "978-0-123456-78-9"),
    ("M0003", "978-0-111111-11-1")
]

for member_id, isbn in borrow_operations:
    success, message = library.borrow_book(member_id, isbn)
    member_name = library.members[member_id].name
    book_title = library.books[isbn].title
    print(f"{member_name} 借阅《{book_title}》: {message}")

# 显示会员借阅情况
print("\n=== 会员借阅情况 ===")
for member in library.members.values():
    print(member)
    for record in member.borrowed_books:
        book = record['book']
        due_date = record['due_date'].strftime('%Y-%m-%d')
        print(f"  - 《{book.title}》(到期日: {due_date})")

# 还书操作
print("\n=== 还书操作 ===")
success, message = library.return_book("M0001", "978-0-123456-78-9")
print(f"张三 归还《Python编程:从入门到实践》: {message}")

# 显示统计信息
print("\n=== 图书馆统计 ===")
stats = library.get_statistics()
for key, value in stats.items():
    print(f"{key}: {value}")

# 七、总结

# 面向对象编程核心概念回顾

  1. 类和对象

    • 类是对象的模板,对象是类的实例
    • 使用__init__方法初始化对象
    • 类变量和实例变量的区别
  2. 封装

    • 使用私有属性(__attribute)隐藏内部实现
    • 使用属性装饰器(@property)控制属性访问
    • 提供公共接口操作私有数据
  3. 继承

    • 子类继承父类的属性和方法
    • 使用super()调用父类方法
    • 方法重写实现多态
    • 多重继承和MRO(方法解析顺序)
  4. 多态

    • 同一接口,不同实现
    • 抽象基类定义接口规范
    • 运行时确定调用哪个方法
  5. 特殊方法

    • 定制对象行为(__str__, __repr__等)
    • 运算符重载(__add__, __eq__等)
    • 上下文管理器(__enter__, __exit__

# 最佳实践

  1. 设计原则

    • 单一职责:每个类只负责一个功能
    • 开闭原则:对扩展开放,对修改关闭
    • 里氏替换:子类可以替换父类
    • 依赖倒置:依赖抽象而不是具体实现
  2. 命名规范

    • 类名使用大驼峰命名(PascalCase)
    • 方法和属性使用小写加下划线(snake_case)
    • 私有属性使用双下划线前缀
    • 常量使用全大写加下划线
  3. 文档和测试

    • 为类和方法编写清晰的文档字符串
    • 使用类型注解提高代码可读性
    • 编写单元测试验证功能正确性

# 下一步学习方向

  1. 设计模式

    • 单例模式、工厂模式、观察者模式等
    • 学习如何解决常见的设计问题
  2. 高级特性

    • 元类(metaclass)
    • 描述符(descriptor)
    • 装饰器的高级用法
  3. 实际应用

    • Web开发中的OOP应用
    • 数据库ORM的设计
    • GUI编程中的事件驱动

# 练习建议

  1. 基础练习

    • 设计一个学生成绩管理系统
    • 实现一个简单的银行账户系统
    • 创建一个动物园管理系统
  2. 进阶练习

    • 设计一个电商购物车系统
    • 实现一个简单的游戏角色系统
    • 创建一个文件管理器
  3. 项目实战

    • 开发一个完整的图书管理系统
    • 实现一个简单的博客系统
    • 创建一个任务管理应用

面向对象编程是Python中非常重要的编程范式,掌握好OOP的概念和技巧,将为你后续学习更高级的Python特性和框架打下坚实的基础。记住,最好的学习方法就是多练习、多实践!