学习目标

通过本章学习,你将掌握: - 类和对象的基本概念 - 属性和方法的定义与使用 - 继承、封装、多态的实现 - 特殊方法(魔术方法)的使用 - 类的高级特性和设计模式 - 抽象类和接口的实现

7.1 类和对象基础

类的定义和实例化

# 基本类定义
class Person:
    """人员类"""
    
    # 类变量(所有实例共享)
    species = "Homo sapiens"
    population = 0
    
    def __init__(self, name, age):
        """构造方法"""
        # 实例变量(每个实例独有)
        self.name = name
        self.age = age
        Person.population += 1  # 更新人口计数
    
    def introduce(self):
        """自我介绍方法"""
        return f"我是{self.name},今年{self.age}岁"
    
    def have_birthday(self):
        """过生日方法"""
        self.age += 1
        return f"{self.name}过生日了,现在{self.age}岁"
    
    @classmethod
    def get_population(cls):
        """类方法:获取人口数量"""
        return cls.population
    
    @staticmethod
    def is_adult(age):
        """静态方法:判断是否成年"""
        return age >= 18

print("=== 类和对象基础 ===")

# 创建实例
person1 = Person("Alice", 25)
person2 = Person("Bob", 17)

# 访问实例变量和方法
print(person1.introduce())
print(person2.introduce())

# 调用实例方法
print(person1.have_birthday())

# 访问类变量
print(f"物种: {Person.species}")
print(f"人口数量: {Person.get_population()}")

# 调用静态方法
print(f"Alice是否成年: {Person.is_adult(person1.age)}")
print(f"Bob是否成年: {Person.is_adult(person2.age)}")

# 动态添加属性
person1.email = "alice@example.com"
print(f"Alice的邮箱: {person1.email}")

# 查看实例属性
print(f"person1的属性: {vars(person1)}")
print(f"person2的属性: {vars(person2)}")

属性访问控制

class BankAccount:
    """银行账户类"""
    
    def __init__(self, account_number, initial_balance=0):
        self.account_number = account_number  # 公开属性
        self._balance = initial_balance       # 受保护属性(约定)
        self.__pin = "1234"                  # 私有属性(名称改写)
        self.__transaction_history = []      # 私有属性
    
    def deposit(self, amount):
        """存款"""
        if amount > 0:
            self._balance += amount
            self.__add_transaction("存款", amount)
            return f"存款成功,余额: {self._balance}"
        return "存款金额必须大于0"
    
    def withdraw(self, amount, pin):
        """取款"""
        if not self.__verify_pin(pin):
            return "PIN码错误"
        
        if amount <= 0:
            return "取款金额必须大于0"
        
        if amount > self._balance:
            return "余额不足"
        
        self._balance -= amount
        self.__add_transaction("取款", amount)
        return f"取款成功,余额: {self._balance}"
    
    def get_balance(self, pin):
        """查询余额"""
        if self.__verify_pin(pin):
            return self._balance
        return "PIN码错误"
    
    def __verify_pin(self, pin):
        """验证PIN码(私有方法)"""
        return pin == self.__pin
    
    def __add_transaction(self, transaction_type, amount):
        """添加交易记录(私有方法)"""
        from datetime import datetime
        self.__transaction_history.append({
            'type': transaction_type,
            'amount': amount,
            'timestamp': datetime.now(),
            'balance': self._balance
        })
    
    def get_transaction_history(self, pin):
        """获取交易历史"""
        if self.__verify_pin(pin):
            return self.__transaction_history.copy()
        return "PIN码错误"
    
    def change_pin(self, old_pin, new_pin):
        """修改PIN码"""
        if self.__verify_pin(old_pin):
            self.__pin = new_pin
            return "PIN码修改成功"
        return "原PIN码错误"

print("\n=== 属性访问控制 ===")

# 创建银行账户
account = BankAccount("123456789", 1000)

# 正常操作
print(account.deposit(500))
print(account.withdraw(200, "1234"))
print(f"余额: {account.get_balance('1234')}")

# 访问公开属性
print(f"账户号: {account.account_number}")

# 访问受保护属性(可以访问,但不建议)
print(f"受保护的余额: {account._balance}")

# 尝试访问私有属性(会报错或访问不到)
try:
    print(account.__pin)  # AttributeError
except AttributeError as e:
    print(f"无法访问私有属性: {e}")

# 通过名称改写访问私有属性(不推荐)
print(f"通过名称改写访问PIN: {account._BankAccount__pin}")

# 查看所有属性
print(f"账户属性: {[attr for attr in dir(account) if not attr.startswith('__') or attr.startswith('_BankAccount__')]}")

属性装饰器

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
    
    @property
    def kelvin(self):
        """开尔文温度属性(只读)"""
        return self._celsius + 273.15
    
    def __str__(self):
        return f"{self._celsius}°C ({self.fahrenheit}°F, {self.kelvin}K)"

print("\n=== 属性装饰器 ===")

# 创建温度对象
temp = Temperature(25)
print(f"初始温度: {temp}")

# 修改摄氏度
temp.celsius = 100
print(f"沸点: {temp}")

# 读取不同单位的温度
print(f"摄氏度: {temp.celsius}")
print(f"华氏度: {temp.fahrenheit}")
print(f"开尔文: {temp.kelvin}")

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

# 尝试直接设置华氏度(会报错,因为没有setter)
try:
    temp.fahrenheit = 100
except AttributeError as e:
    print(f"无法设置华氏度: {e}")

# 使用property的另一种方式
class Circle:
    """圆形类"""
    
    def __init__(self, radius):
        self._radius = radius
    
    def get_radius(self):
        """获取半径"""
        return self._radius
    
    def set_radius(self, value):
        """设置半径"""
        if value <= 0:
            raise ValueError("半径必须大于0")
        self._radius = value
    
    def get_area(self):
        """获取面积"""
        import math
        return math.pi * self._radius ** 2
    
    def get_circumference(self):
        """获取周长"""
        import math
        return 2 * math.pi * self._radius
    
    # 使用property函数创建属性
    radius = property(get_radius, set_radius)
    area = property(get_area)
    circumference = property(get_circumference)
    
    def __str__(self):
        return f"圆形(半径={self.radius}, 面积={self.area:.2f}, 周长={self.circumference:.2f})"

print("\n=== property函数方式 ===")
circle = Circle(5)
print(circle)

circle.radius = 10
print(circle)

try:
    circle.radius = -5
except ValueError as e:
    print(f"半径设置错误: {e}")

运行类和对象基础示例:

python oop_basics.py

7.2 继承和多态

单继承

# 基类(父类)
class Animal:
    """动物基类"""
    
    def __init__(self, name, species):
        self.name = name
        self.species = species
        self.is_alive = True
    
    def eat(self, food):
        """吃东西"""
        return f"{self.name}正在吃{food}"
    
    def sleep(self):
        """睡觉"""
        return f"{self.name}正在睡觉"
    
    def make_sound(self):
        """发出声音(基类中的通用实现)"""
        return f"{self.name}发出了声音"
    
    def __str__(self):
        return f"{self.species}: {self.name}"

# 派生类(子类)
class Dog(Animal):
    """狗类"""
    
    def __init__(self, name, breed):
        # 调用父类构造方法
        super().__init__(name, "狗")
        self.breed = breed
        self.loyalty = 100
    
    def make_sound(self):
        """重写父类方法"""
        return f"{self.name}汪汪叫"
    
    def fetch(self, item):
        """狗特有的方法"""
        return f"{self.name}去捡{item}"
    
    def wag_tail(self):
        """摇尾巴"""
        return f"{self.name}开心地摇尾巴"
    
    def __str__(self):
        return f"{self.breed}狗: {self.name}"

class Cat(Animal):
    """猫类"""
    
    def __init__(self, name, color):
        super().__init__(name, "猫")
        self.color = color
        self.independence = 80
    
    def make_sound(self):
        """重写父类方法"""
        return f"{self.name}喵喵叫"
    
    def climb(self, target):
        """猫特有的方法"""
        return f"{self.name}爬上了{target}"
    
    def purr(self):
        """呼噜声"""
        return f"{self.name}发出呼噜声"
    
    def __str__(self):
        return f"{self.color}猫: {self.name}"

class Bird(Animal):
    """鸟类"""
    
    def __init__(self, name, wing_span):
        super().__init__(name, "鸟")
        self.wing_span = wing_span
        self.can_fly = True
    
    def make_sound(self):
        """重写父类方法"""
        return f"{self.name}啾啾叫"
    
    def fly(self, destination):
        """鸟特有的方法"""
        if self.can_fly:
            return f"{self.name}飞向{destination}"
        return f"{self.name}不能飞行"
    
    def __str__(self):
        return f"鸟: {self.name} (翼展: {self.wing_span}cm)"

print("=== 单继承示例 ===")

# 创建不同的动物
dog = Dog("旺财", "金毛")
cat = Cat("咪咪", "橘色")
bird = Bird("小黄", 25)

# 调用继承的方法
print(dog.eat("狗粮"))
print(cat.sleep())
print(bird.eat("虫子"))

# 调用重写的方法
print(dog.make_sound())
print(cat.make_sound())
print(bird.make_sound())

# 调用特有的方法
print(dog.fetch("球"))
print(cat.climb("树"))
print(bird.fly("南方"))

# 多态演示
animals = [dog, cat, bird]

print("\n=== 多态演示 ===")
for animal in animals:
    print(f"{animal}: {animal.make_sound()}")

# 检查继承关系
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)}")

# 查看方法解析顺序(MRO)
print(f"Dog的MRO: {Dog.__mro__}")
print(f"Dog的MRO(名称): {[cls.__name__ for cls in Dog.__mro__]}")

多重继承

# 多重继承示例
class Flyable:
    """可飞行的混入类"""
    
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.altitude = 0
    
    def take_off(self):
        """起飞"""
        self.altitude = 100
        return f"起飞,当前高度: {self.altitude}米"
    
    def land(self):
        """降落"""
        self.altitude = 0
        return f"降落,当前高度: {self.altitude}米"
    
    def fly_to_altitude(self, target_altitude):
        """飞到指定高度"""
        self.altitude = target_altitude
        return f"飞行到{target_altitude}米高度"

class Swimmable:
    """可游泳的混入类"""
    
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.depth = 0
    
    def dive(self, target_depth):
        """潜水"""
        self.depth = target_depth
        return f"潜水到{target_depth}米深度"
    
    def surface(self):
        """浮出水面"""
        self.depth = 0
        return f"浮出水面,当前深度: {self.depth}米"
    
    def swim(self, direction):
        """游泳"""
        return f"向{direction}游泳"

class Duck(Animal, Flyable, Swimmable):
    """鸭子类(多重继承)"""
    
    def __init__(self, name):
        # 使用super()确保所有父类都被正确初始化
        super().__init__(name, "鸭子")
    
    def make_sound(self):
        """重写父类方法"""
        return f"{self.name}嘎嘎叫"
    
    def quack(self):
        """鸭子特有的叫声"""
        return f"{self.name}发出响亮的嘎嘎声"

class Penguin(Animal, Swimmable):
    """企鹅类(不能飞行,但能游泳)"""
    
    def __init__(self, name):
        super().__init__(name, "企鹅")
    
    def make_sound(self):
        return f"{self.name}发出企鹅叫声"
    
    def slide_on_ice(self):
        """在冰上滑行"""
        return f"{self.name}在冰上滑行"

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

# 创建鸭子和企鹅
duck = Duck("唐老鸭")
penguin = Penguin("波波")

# 鸭子的多种能力
print(duck.make_sound())
print(duck.eat("鱼"))
print(duck.take_off())
print(duck.fly_to_altitude(200))
print(duck.land())
print(duck.dive(5))
print(duck.swim("北方"))
print(duck.surface())

print()
# 企鹅的能力
print(penguin.make_sound())
print(penguin.dive(20))
print(penguin.swim("东方"))
print(penguin.slide_on_ice())
print(penguin.surface())

# 检查多重继承的MRO
print(f"\nDuck的MRO: {[cls.__name__ for cls in Duck.__mro__]}")
print(f"Penguin的MRO: {[cls.__name__ for cls in Penguin.__mro__]}")

# 检查实例关系
print(f"\nduck是Animal的实例: {isinstance(duck, Animal)}")
print(f"duck是Flyable的实例: {isinstance(duck, Flyable)}")
print(f"duck是Swimmable的实例: {isinstance(duck, Swimmable)}")
print(f"penguin是Flyable的实例: {isinstance(penguin, Flyable)}")

抽象基类

from abc import ABC, abstractmethod

# 抽象基类
class Shape(ABC):
    """形状抽象基类"""
    
    def __init__(self, name):
        self.name = name
    
    @abstractmethod
    def area(self):
        """计算面积(抽象方法)"""
        pass
    
    @abstractmethod
    def perimeter(self):
        """计算周长(抽象方法)"""
        pass
    
    def describe(self):
        """描述形状(具体方法)"""
        return f"{self.name}: 面积={self.area():.2f}, 周长={self.perimeter():.2f}"
    
    def __str__(self):
        return self.name

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 __str__(self):
        return f"矩形({self.width}x{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 __str__(self):
        return f"圆形(半径={self.radius})"

class Triangle(Shape):
    """三角形类"""
    
    def __init__(self, a, b, c):
        super().__init__("三角形")
        self.a = a
        self.b = b
        self.c = c
        
        # 验证三角形的有效性
        if not (a + b > c and b + c > a and a + c > b):
            raise ValueError("无效的三角形边长")
    
    def area(self):
        """使用海伦公式计算面积"""
        s = self.perimeter() / 2
        import math
        return math.sqrt(s * (s - self.a) * (s - self.b) * (s - self.c))
    
    def perimeter(self):
        """实现抽象方法"""
        return self.a + self.b + self.c
    
    def __str__(self):
        return f"三角形({self.a}, {self.b}, {self.c})"

print("\n=== 抽象基类示例 ===")

# 创建具体形状
rectangle = Rectangle(5, 3)
circle = Circle(4)
triangle = Triangle(3, 4, 5)

shapes = [rectangle, circle, triangle]

# 多态调用
for shape in shapes:
    print(shape.describe())

# 尝试实例化抽象类(会报错)
try:
    abstract_shape = Shape("抽象形状")
except TypeError as e:
    print(f"\n无法实例化抽象类: {e}")

# 形状计算器
class ShapeCalculator:
    """形状计算器"""
    
    @staticmethod
    def total_area(shapes):
        """计算总面积"""
        return sum(shape.area() for shape in shapes)
    
    @staticmethod
    def total_perimeter(shapes):
        """计算总周长"""
        return sum(shape.perimeter() for shape in shapes)
    
    @staticmethod
    def largest_shape(shapes):
        """找到面积最大的形状"""
        return max(shapes, key=lambda shape: shape.area())
    
    @staticmethod
    def sort_by_area(shapes):
        """按面积排序"""
        return sorted(shapes, key=lambda shape: shape.area())

print("\n=== 形状计算器 ===")
calculator = ShapeCalculator()

print(f"总面积: {calculator.total_area(shapes):.2f}")
print(f"总周长: {calculator.total_perimeter(shapes):.2f}")
print(f"最大形状: {calculator.largest_shape(shapes)}")

print("\n按面积排序:")
for shape in calculator.sort_by_area(shapes):
    print(f"  {shape}: {shape.area():.2f}")

运行继承和多态示例:

python inheritance_polymorphism.py

7.3 特殊方法(魔术方法)

基本特殊方法

class Vector:
    """二维向量类"""
    
    def __init__(self, x, y):
        self.x = x
        self.y = y
    
    def __str__(self):
        """字符串表示(用户友好)"""
        return f"Vector({self.x}, {self.y})"
    
    def __repr__(self):
        """字符串表示(开发者友好)"""
        return f"Vector({self.x!r}, {self.y!r})"
    
    def __eq__(self, other):
        """相等比较"""
        if isinstance(other, Vector):
            return self.x == other.x and self.y == other.y
        return False
    
    def __ne__(self, other):
        """不等比较"""
        return not self.__eq__(other)
    
    def __lt__(self, other):
        """小于比较(按长度)"""
        if isinstance(other, Vector):
            return self.magnitude() < other.magnitude()
        return NotImplemented
    
    def __le__(self, other):
        """小于等于比较"""
        return self < other or self == other
    
    def __gt__(self, other):
        """大于比较"""
        if isinstance(other, Vector):
            return self.magnitude() > other.magnitude()
        return NotImplemented
    
    def __ge__(self, other):
        """大于等于比较"""
        return self > other or self == other
    
    def __add__(self, other):
        """向量加法"""
        if isinstance(other, Vector):
            return Vector(self.x + other.x, self.y + other.y)
        return NotImplemented
    
    def __sub__(self, other):
        """向量减法"""
        if isinstance(other, Vector):
            return Vector(self.x - other.x, self.y - other.y)
        return NotImplemented
    
    def __mul__(self, scalar):
        """标量乘法"""
        if isinstance(scalar, (int, float)):
            return Vector(self.x * scalar, self.y * scalar)
        return NotImplemented
    
    def __rmul__(self, scalar):
        """右乘法(支持 scalar * vector)"""
        return self.__mul__(scalar)
    
    def __truediv__(self, scalar):
        """标量除法"""
        if isinstance(scalar, (int, float)) and scalar != 0:
            return Vector(self.x / scalar, self.y / scalar)
        return NotImplemented
    
    def __neg__(self):
        """负号"""
        return Vector(-self.x, -self.y)
    
    def __abs__(self):
        """绝对值(向量长度)"""
        return self.magnitude()
    
    def __bool__(self):
        """布尔值(零向量为False)"""
        return self.x != 0 or self.y != 0
    
    def __hash__(self):
        """哈希值(使对象可以作为字典键)"""
        return hash((self.x, self.y))
    
    def magnitude(self):
        """计算向量长度"""
        import math
        return math.sqrt(self.x ** 2 + self.y ** 2)
    
    def dot(self, other):
        """点积"""
        if isinstance(other, Vector):
            return self.x * other.x + self.y * other.y
        raise TypeError("点积需要另一个向量")
    
    def normalize(self):
        """归一化向量"""
        mag = self.magnitude()
        if mag == 0:
            raise ValueError("零向量无法归一化")
        return Vector(self.x / mag, self.y / mag)

print("=== 特殊方法示例 ===")

# 创建向量
v1 = Vector(3, 4)
v2 = Vector(1, 2)
v3 = Vector(3, 4)

# 字符串表示
print(f"v1: {v1}")
print(f"v1 repr: {repr(v1)}")

# 比较操作
print(f"v1 == v3: {v1 == v3}")
print(f"v1 == v2: {v1 == v2}")
print(f"v1 > v2: {v1 > v2}")
print(f"v1 < v2: {v1 < v2}")

# 算术操作
print(f"v1 + v2: {v1 + v2}")
print(f"v1 - v2: {v1 - v2}")
print(f"v1 * 2: {v1 * 2}")
print(f"3 * v2: {3 * v2}")
print(f"v1 / 2: {v1 / 2}")
print(f"-v1: {-v1}")

# 其他操作
print(f"abs(v1): {abs(v1)}")
print(f"bool(v1): {bool(v1)}")
print(f"bool(Vector(0, 0)): {bool(Vector(0, 0))}")

# 向量运算
print(f"v1 · v2: {v1.dot(v2)}")
print(f"v1 归一化: {v1.normalize()}")

# 作为字典键
vector_dict = {v1: "向量1", v2: "向量2"}
print(f"字典: {vector_dict}")
print(f"v3在字典中: {v3 in vector_dict}")

容器类型特殊方法

class Matrix:
    """矩阵类"""
    
    def __init__(self, data):
        """初始化矩阵"""
        if not data or not data[0]:
            raise ValueError("矩阵不能为空")
        
        # 检查所有行的长度是否相同
        row_length = len(data[0])
        if not all(len(row) == row_length for row in data):
            raise ValueError("所有行必须有相同的长度")
        
        self.data = [list(row) for row in data]  # 深拷贝
        self.rows = len(data)
        self.cols = len(data[0])
    
    def __str__(self):
        """字符串表示"""
        return '\n'.join([' '.join(f'{cell:6.2f}' for cell in row) for row in self.data])
    
    def __repr__(self):
        return f"Matrix({self.data!r})"
    
    def __getitem__(self, key):
        """获取元素或行"""
        if isinstance(key, tuple):
            row, col = key
            return self.data[row][col]
        else:
            return self.data[key]
    
    def __setitem__(self, key, value):
        """设置元素或行"""
        if isinstance(key, tuple):
            row, col = key
            self.data[row][col] = value
        else:
            if len(value) != self.cols:
                raise ValueError(f"行长度必须为{self.cols}")
            self.data[key] = list(value)
    
    def __len__(self):
        """返回行数"""
        return self.rows
    
    def __iter__(self):
        """迭代行"""
        return iter(self.data)
    
    def __contains__(self, item):
        """检查是否包含某个值"""
        for row in self.data:
            if item in row:
                return True
        return False
    
    def __add__(self, other):
        """矩阵加法"""
        if not isinstance(other, Matrix):
            return NotImplemented
        
        if self.rows != other.rows or self.cols != other.cols:
            raise ValueError("矩阵维度必须相同")
        
        result = []
        for i in range(self.rows):
            row = []
            for j in range(self.cols):
                row.append(self.data[i][j] + other.data[i][j])
            result.append(row)
        
        return Matrix(result)
    
    def __mul__(self, other):
        """矩阵乘法或标量乘法"""
        if isinstance(other, (int, float)):
            # 标量乘法
            result = []
            for i in range(self.rows):
                row = [cell * other for cell in self.data[i]]
                result.append(row)
            return Matrix(result)
        
        elif isinstance(other, Matrix):
            # 矩阵乘法
            if self.cols != other.rows:
                raise ValueError(f"无法相乘:{self.rows}x{self.cols} 和 {other.rows}x{other.cols}")
            
            result = []
            for i in range(self.rows):
                row = []
                for j in range(other.cols):
                    cell = sum(self.data[i][k] * other.data[k][j] for k in range(self.cols))
                    row.append(cell)
                result.append(row)
            
            return Matrix(result)
        
        return NotImplemented
    
    def __eq__(self, other):
        """相等比较"""
        if not isinstance(other, Matrix):
            return False
        return self.data == other.data
    
    def transpose(self):
        """转置矩阵"""
        result = []
        for j in range(self.cols):
            row = [self.data[i][j] for i in range(self.rows)]
            result.append(row)
        return Matrix(result)
    
    def shape(self):
        """返回矩阵形状"""
        return (self.rows, self.cols)

print("\n=== 容器类型特殊方法 ===")

# 创建矩阵
m1 = Matrix([[1, 2, 3], [4, 5, 6]])
m2 = Matrix([[7, 8, 9], [10, 11, 12]])
m3 = Matrix([[1, 2], [3, 4], [5, 6]])

print("矩阵 m1:")
print(m1)
print(f"形状: {m1.shape()}")

# 索引访问
print(f"\nm1[0]: {m1[0]}")
print(f"m1[1, 2]: {m1[1, 2]}")

# 修改元素
m1[0, 0] = 100
print(f"修改后 m1[0, 0]: {m1[0, 0]}")

# 长度和迭代
print(f"\nm1 长度: {len(m1)}")
print("迭代 m1:")
for i, row in enumerate(m1):
    print(f"  行 {i}: {row}")

# 包含检查
print(f"\n5 在 m1 中: {5 in m1}")
print(f"100 在 m1 中: {100 in m1}")

# 矩阵运算
print("\n矩阵加法 m1 + m2:")
print(m1 + m2)

print("\n标量乘法 m1 * 2:")
print(m1 * 2)

print("\n矩阵乘法 m1 * m3:")
print(m1 * m3)

print("\nm1 转置:")
print(m1.transpose())

上下文管理器

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 Timer:
    """计时器上下文管理器"""
    
    def __init__(self, name="操作"):
        self.name = name
        self.start_time = None
    
    def __enter__(self):
        import time
        self.start_time = time.time()
        print(f"开始{self.name}...")
        return self
    
    def __exit__(self, exc_type, exc_value, traceback):
        import time
        end_time = time.time()
        duration = end_time - self.start_time
        print(f"{self.name}完成,耗时: {duration:.4f}秒")
        return False

class DatabaseConnection:
    """数据库连接上下文管理器"""
    
    def __init__(self, connection_string):
        self.connection_string = connection_string
        self.connection = None
        self.transaction = None
    
    def __enter__(self):
        print(f"连接数据库: {self.connection_string}")
        # 模拟数据库连接
        self.connection = f"Connection to {self.connection_string}"
        print("开始事务")
        self.transaction = "Transaction started"
        return self
    
    def __exit__(self, exc_type, exc_value, traceback):
        if exc_type is None:
            print("提交事务")
        else:
            print(f"回滚事务,原因: {exc_value}")
        
        print("关闭数据库连接")
        self.connection = None
        self.transaction = None
        return False  # 不抑制异常
    
    def execute(self, query):
        """执行查询"""
        if not self.connection:
            raise RuntimeError("数据库未连接")
        print(f"执行查询: {query}")
        return f"Result of {query}"

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

# 文件管理器示例
print("1. 文件管理器:")
try:
    with FileManager("test.txt", "w") as f:
        f.write("Hello, World!")
        f.write("\nThis is a test file.")
except FileNotFoundError as e:
    print(f"文件操作失败: {e}")

# 计时器示例
print("\n2. 计时器:")
with Timer("数据处理"):
    import time
    time.sleep(0.1)  # 模拟耗时操作
    result = sum(range(1000000))
    print(f"计算结果: {result}")

# 数据库连接示例
print("\n3. 数据库连接(正常情况):")
with DatabaseConnection("localhost:5432/mydb") as db:
    db.execute("SELECT * FROM users")
    db.execute("UPDATE users SET active = 1")

print("\n4. 数据库连接(异常情况):")
try:
    with DatabaseConnection("localhost:5432/mydb") as db:
        db.execute("SELECT * FROM users")
        raise ValueError("模拟数据库错误")
        db.execute("UPDATE users SET active = 1")  # 不会执行
except ValueError as e:
    print(f"捕获异常: {e}")

# 嵌套上下文管理器
print("\n5. 嵌套上下文管理器:")
with Timer("数据库操作"):
    with DatabaseConnection("localhost:5432/mydb") as db:
        db.execute("SELECT COUNT(*) FROM users")
        with Timer("复杂查询"):
            time.sleep(0.05)  # 模拟复杂查询
            db.execute("SELECT * FROM users JOIN orders ON users.id = orders.user_id")

运行特殊方法示例:

python special_methods.py

本章小结

本章我们深入学习了Python的面向对象编程:

  1. 类和对象基础:类定义、实例化、属性访问控制、属性装饰器
  2. 继承和多态:单继承、多重继承、方法重写、抽象基类
  3. 特殊方法:运算符重载、容器协议、上下文管理器

下一章预告

下一章我们将学习《异常处理和调试》,内容包括: - 异常的类型和处理 - 自定义异常 - 调试技巧和工具 - 日志记录 - 单元测试

练习题

基础练习

  1. 类设计

    • 设计一个学生管理系统
    • 实现一个简单的银行账户类
    • 创建一个图书馆管理系统
  2. 继承实践

    • 设计一个动物园管理系统
    • 实现不同类型的员工类
    • 创建一个游戏角色系统

进阶练习

  1. 特殊方法

    • 实现一个自定义的列表类
    • 创建一个复数类
    • 设计一个自定义的字典类
  2. 设计模式

    • 实现单例模式
    • 创建工厂模式
    • 设计观察者模式

提示:面向对象编程是Python的核心特性,理解类、继承、多态等概念对于编写高质量的Python代码至关重要。多练习不同的设计模式和应用场景。