python-面向对象

17 minute read

Python 面向对象编程


一、面向对象编程基础

1.1 面向对象概念

  • 什么是面向对象编程 (OOP)
    • 一种编程范式,将现实世界的事物抽象为”对象”
    • 对象包含属性(数据)和方法(行为)
    • 通过对象之间的交互来构建程序
  • 面向对象三大特征
    • 封装:隐藏内部实现细节,提供公共接口
    • 继承:子类继承父类的属性和方法,实现代码复用
    • 多态:同一操作作用于不同对象产生不同的行为
  • 面向对象 vs 面向过程
    • 面向过程:以”函数”为中心,关注”怎么做”
    • 面向对象:以”对象”为中心,关注”谁来做”

1.2 类与对象

  • 类 (Class)
    • 对象的蓝图或模板
    • 定义对象的属性和方法
    • 是抽象的数据类型
  • 对象 (Object)
    • 类的具体实例
    • 拥有类定义的属性和方法
    • 是具体的数据实例
# 定义类
class Person:
    """人类"""
    pass

# 创建对象
person1 = Person()  # 实例化
person2 = Person()  # 另一个实例

1.3 面向对象设计原则

  1. 单一职责原则 (SRP):一个类只负责一个功能领域
  2. 开闭原则 (OCP):对扩展开放,对修改关闭
  3. 里氏替换原则 (LSP):子类可以替换父类
  4. 接口隔离原则 (ISP):使用多个专门的接口
  5. 依赖倒置原则 (DIP):依赖抽象,不依赖具体实现

二、类的基本结构与使用

2.1 定义类

class Person:
    """这是一个人类"""
    # 类属性
    species = "Human"
    
    def __init__(self, name, age):
        """构造方法,初始化实例属性"""
        self.name = name  # 实例属性
        self.age = age
        self.__private_attr = "私有属性"  # 私有属性
    
    def say_hello(self):
        """实例方法"""
        return f"Hello, I'm {self.name}, {self.age} years old."
    
    @classmethod
    def get_species(cls):
        """类方法"""
        return f"Species: {cls.species}"
    
    @staticmethod
    def is_adult(age):
        """静态方法"""
        return age >= 18

2.2 构造函数与初始化

  • __init__ 方法
    • 对象创建时自动调用
    • 用于初始化对象属性
    • 可以接收参数
class Student:
    def __init__(self, name, age, student_id):
        self.name = name
        self.age = age
        self.student_id = student_id
        self.grades = []  # 初始化空列表
    
    def add_grade(self, grade):
        self.grades.append(grade)
    
    def get_average(self):
        if not self.grades:
            return 0
        return sum(self.grades) / len(self.grades)

# 使用
student = Student("张三", 20, "2023001")
student.add_grade(90)
student.add_grade(85)
print(student.get_average())  # 87.5

2.3 实例属性 vs 类属性

  • 实例属性:属于具体对象,每个对象独立
  • 类属性:属于类,所有对象共享
class Dog:
    # 类属性
    species = "Canis familiaris"
    count = 0  # 记录创建的实例数量
    
    def __init__(self, name, breed):
        # 实例属性
        self.name = name
        self.breed = breed
        Dog.count += 1  # 每次创建实例,计数器加1
    
    def bark(self):
        return f"{self.name} says Woof!"

# 测试
dog1 = Dog("Buddy", "Golden Retriever")
dog2 = Dog("Max", "German Shepherd")

print(dog1.name)  # Buddy
print(dog2.name)  # Max
print(dog1.species)  # Canis familiaris
print(dog2.species)  # Canis familiaris
print(Dog.count)  # 2

2.4 方法类型

  1. 实例方法
    • 第一个参数是 self,指向实例本身
    • 可以访问和修改实例属性
    • 可以访问类属性
    class Calculator:
        def __init__(self, initial_value=0):
            self.value = initial_value
            
        def add(self, x):
            """实例方法"""
            self.value += x
            return self
            
        def multiply(self, x):
            """实例方法"""
            self.value *= x
            return self
            
        def get_value(self):
            return self.value
    
    # 链式调用
    calc = Calculator(10)
    result = calc.add(5).multiply(2).get_value()
    print(result)  # 30
    
  2. 类方法
    • 使用 @classmethod 装饰器
    • 第一个参数是 cls,指向类本身
    • 可以访问和修改类属性
    • 不能访问实例属性
    class Circle:
        pi = 3.14159
            
        def __init__(self, radius):
            self.radius = radius
            
        @classmethod
        def from_diameter(cls, diameter):
            """类方法:通过直径创建圆"""
            return cls(diameter / 2)
            
        @classmethod
        def get_pi(cls):
            """类方法:获取π值"""
            return cls.pi
            
        def area(self):
            return self.pi * self.radius ** 2
    
    # 使用类方法创建实例
    circle1 = Circle(5)
    circle2 = Circle.from_diameter(10)
    print(circle1.radius)  # 5
    print(circle2.radius)  # 5
    print(Circle.get_pi())  # 3.14159
    
  3. 静态方法
    • 使用 @staticmethod 装饰器
    • 没有 selfcls 参数
    • 与类和实例无关,只是逻辑上属于类
    • 不能访问类属性和实例属性
    class MathUtils:
        @staticmethod
        def add(a, b):
            return a + b
            
        @staticmethod
        def multiply(a, b):
            return a * b
            
        @staticmethod
        def factorial(n):
            if n == 0:
                return 1
            return n * MathUtils.factorial(n-1)
    
    # 使用静态方法
    print(MathUtils.add(5, 3))  # 8
    print(MathUtils.multiply(4, 6))  # 24
    print(MathUtils.factorial(5))  # 120
    

三、封装

3.1 访问控制

  • 公有成员:以常规方式命名,可被外部访问
  • 保护成员:以单个下划线开头 _,约定为内部使用
  • 私有成员:以双下划线开头 __,名称会被改写,实现伪私有
class BankAccount:
    def __init__(self, owner, initial_balance=0):
        self.owner = owner  # 公有属性
        self._balance = initial_balance  # 保护属性
        self.__pin = "1234"  # 私有属性
    
    def deposit(self, amount):
        if amount > 0:
            self._balance += amount
            return True
        return False
    
    def withdraw(self, amount, pin):
        if pin == self.__pin and 0 < amount <= self._balance:
            self._balance -= amount
            return True
        return False
    
    def get_balance(self):
        return self._balance

# 测试
account = BankAccount("张三", 1000)
print(account.owner)  # 张三
print(account.get_balance())  # 1000
account.deposit(500)
print(account.get_balance())  # 1500
print(account._balance)  # 1500(不推荐直接访问保护属性)
# print(account.__pin)  # 错误:AttributeError
print(account._BankAccount__pin)  # 1234(名称被改写,但仍可访问)

3.2 属性装饰器

  • @property:将方法转换为只读属性
  • @属性名.setter:设置属性的setter方法
  • @属性名.deleter:删除属性的deleter方法
class Rectangle:
    def __init__(self, width, height):
        self._width = width
        self._height = height
    
    @property
    def width(self):
        """获取宽度"""
        return self._width
    
    @width.setter
    def width(self, value):
        """设置宽度"""
        if value <= 0:
            raise ValueError("宽度必须大于0")
        self._width = value
    
    @property
    def height(self):
        """获取高度"""
        return self._height
    
    @height.setter
    def height(self, value):
        """设置高度"""
        if value <= 0:
            raise ValueError("高度必须大于0")
        self._height = value
    
    @property
    def area(self):
        """计算面积(只读属性)"""
        return self._width * self._height
    
    @property
    def perimeter(self):
        """计算周长(只读属性)"""
        return 2 * (self._width + self._height)

# 测试
rect = Rectangle(10, 5)
print(f"宽度: {rect.width}, 高度: {rect.height}")  # 宽度: 10, 高度: 5
print(f"面积: {rect.area}")  # 面积: 50
print(f"周长: {rect.perimeter}")  # 周长: 30

rect.width = 20
rect.height = 8
print(f"新面积: {rect.area}")  # 新面积: 160

3.3 只读属性与计算属性

class Circle:
    def __init__(self, radius):
        self._radius = radius
    
    @property
    def radius(self):
        return self._radius
    
    @property
    def diameter(self):
        """计算属性:直径"""
        return 2 * self._radius
    
    @property
    def area(self):
        """计算属性:面积"""
        return 3.14159 * self._radius ** 2
    
    @property
    def circumference(self):
        """计算属性:周长"""
        return 2 * 3.14159 * self._radius

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

四、继承

4.1 单继承

# 父类(基类)
class Animal:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    
    def eat(self):
        return f"{self.name} is eating."
    
    def sleep(self):
        return f"{self.name} is sleeping."
    
    def make_sound(self):
        return "Some generic animal sound"

# 子类(派生类)
class Dog(Animal):
    def __init__(self, name, age, breed):
        # 调用父类的构造方法
        super().__init__(name, age)
        self.breed = breed
    
    def make_sound(self):
        """重写父类方法"""
        return "Woof! Woof!"
    
    def fetch(self):
        """子类特有的方法"""
        return f"{self.name} is fetching the ball."

class Cat(Animal):
    def __init__(self, name, age, color):
        super().__init__(name, age)
        self.color = color
    
    def make_sound(self):
        """重写父类方法"""
        return "Meow!"
    
    def climb(self):
        """子类特有的方法"""
        return f"{self.name} is climbing a tree."

# 测试
dog = Dog("Buddy", 3, "Golden Retriever")
cat = Cat("Whiskers", 2, "White")

print(dog.eat())  # Buddy is eating.
print(dog.make_sound())  # Woof! Woof!
print(dog.fetch())  # Buddy is fetching the ball.

print(cat.sleep())  # Whiskers is sleeping.
print(cat.make_sound())  # Meow!
print(cat.climb())  # Whiskers is climbing a tree.

4.2 多继承

  • 多个父类:一个子类可以继承多个父类
  • 方法解析顺序 (MRO):决定方法的搜索顺序
class Engine:
    def __init__(self, horsepower):
        self.horsepower = horsepower
    
    def start(self):
        return "Engine started"
    
    def stop(self):
        return "Engine stopped"

class ElectricSystem:
    def __init__(self, battery_capacity):
        self.battery_capacity = battery_capacity
    
    def charge(self):
        return "Charging electric system"
    
    def check_battery(self):
        return f"Battery: {self.battery_capacity} kWh"

class HybridCar(Engine, ElectricSystem):
    def __init__(self, horsepower, battery_capacity, model):
        # 分别初始化两个父类
        Engine.__init__(self, horsepower)
        ElectricSystem.__init__(self, battery_capacity)
        self.model = model
    
    def drive(self):
        return f"{self.model} is driving with {self.horsepower} HP"
    
    def hybrid_mode(self):
        return "Switching to hybrid mode"

# 测试
car = HybridCar(150, 20, "Prius")
print(car.start())  # Engine started
print(car.charge())  # Charging electric system
print(car.check_battery())  # Battery: 20 kWh
print(car.drive())  # Prius is driving with 150 HP

# 查看MRO
print(HybridCar.__mro__)

4.3 方法重写

  • 完全重写:重新实现父类方法
  • 扩展重写:调用父类方法,添加额外功能
class Vehicle:
    def __init__(self, brand, model):
        self.brand = brand
        self.model = model
    
    def start(self):
        return f"{self.brand} {self.model} is starting"
    
    def get_info(self):
        return f"Vehicle: {self.brand} {self.model}"

class ElectricCar(Vehicle):
    def __init__(self, brand, model, battery_capacity):
        super().__init__(brand, model)
        self.battery_capacity = battery_capacity
    
    def start(self):
        """完全重写"""
        return f"{self.brand} {self.model} (Electric) is starting silently"
    
    def get_info(self):
        """扩展重写"""
        base_info = super().get_info()
        return f"{base_info}, Battery: {self.battery_capacity}kWh"

# 测试
car = ElectricCar("Tesla", "Model 3", 75)
print(car.start())  # Tesla Model 3 (Electric) is starting silently
print(car.get_info())  # Vehicle: Tesla Model 3, Battery: 75kWh

4.4 抽象基类

  • 定义接口:规定子类必须实现的方法
  • abc 模块:提供抽象基类支持
  • @abstractmethod:抽象方法装饰器
from abc import ABC, abstractmethod

# 抽象基类
class Shape(ABC):
    @abstractmethod
    def area(self):
        """计算面积(抽象方法)"""
        pass
    
    @abstractmethod
    def perimeter(self):
        """计算周长(抽象方法)"""
        pass
    
    def describe(self):
        """具体方法"""
        return f"This is a {self.__class__.__name__}"

# 具体子类
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):
        """实现抽象方法"""
        return 3.14159 * self.radius ** 2
    
    def perimeter(self):
        """实现抽象方法"""
        return 2 * 3.14159 * self.radius

# 测试
shapes = [Rectangle(10, 5), Circle(7)]
for shape in shapes:
    print(shape.describe())
    print(f"面积: {shape.area():.2f}")
    print(f"周长: {shape.perimeter():.2f}")
    print("-" * 30)

五、多态

5.1 多态概念

  • 定义:同一操作作用于不同的对象,可以有不同的解释
  • 实现方式:继承 + 方法重写
  • 优点:提高代码的灵活性和可扩展性
class Animal:
    def make_sound(self):
        return "Some animal sound"

class Dog(Animal):
    def make_sound(self):
        return "Woof!"

class Cat(Animal):
    def make_sound(self):
        return "Meow!"

class Duck(Animal):
    def make_sound(self):
        return "Quack!"

# 多态示例
animals = [Dog(), Cat(), Duck(), Animal()]

for animal in animals:
    print(animal.make_sound())
# 输出:
# Woof!
# Meow!
# Quack!
# Some animal sound

5.2 鸭子类型

  • “如果它走起路来像鸭子,叫起来也像鸭子,那么它就是鸭子”
  • 不关心对象类型,只关心对象的行为
  • Python 动态类型的优势
# 不需要继承同一个父类
class Dog:
    def make_sound(self):
        return "Woof!"

class Car:
    def make_sound(self):
        return "Vroom!"

class Person:
    def make_sound(self):
        return "Hello!"

# 鸭子类型:只要对象有 make_sound 方法
def make_it_talk(obj):
    return obj.make_sound()

# 测试
objects = [Dog(), Car(), Person()]
for obj in objects:
    print(make_it_talk(obj))
# 输出:
# Woof!
# Vroom!
# Hello!

5.3 运算符重载

  • 特殊方法:以双下划线开头和结尾
  • 自定义对象行为:使对象支持内置运算
class Vector:
    def __init__(self, x, y):
        self.x = x
        self.y = y
    
    def __str__(self):
        """str() 函数调用"""
        return f"Vector({self.x}, {self.y})"
    
    def __repr__(self):
        """repr() 函数调用,用于调试"""
        return f"Vector({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 __eq__(self, other):
        """== 运算符重载"""
        if isinstance(other, Vector):
            return self.x == other.x and self.y == other.y
        return False
    
    def __len__(self):
        """len() 函数调用,返回维度"""
        return 2
    
    def __getitem__(self, index):
        """[] 索引访问"""
        if index == 0:
            return self.x
        elif index == 1:
            return self.y
        raise IndexError("Vector 索引超出范围")

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

print(v1)  # Vector(3, 4)
print(v1 + v2)  # Vector(4, 6)
print(v1 - v2)  # Vector(2, 2)
print(v1 * 2)  # Vector(6, 8)
print(v1 == Vector(3, 4))  # True
print(len(v1))  # 2
print(v1[0], v1[1])  # 3 4

六、特殊方法与魔法方法

6.1 对象创建与销毁

class Resource:
    def __new__(cls, *args, **kwargs):
        """创建实例时调用,在 __init__ 之前"""
        print("__new__ 被调用")
        instance = super().__new__(cls)
        return instance
    
    def __init__(self, name):
        """初始化实例"""
        print("__init__ 被调用")
        self.name = name
        self.is_open = False
    
    def __del__(self):
        """对象被销毁时调用"""
        print(f"__del__ 被调用: {self.name}")
    
    def open(self):
        self.is_open = True
        print(f"Resource {self.name} opened")
    
    def close(self):
        self.is_open = False
        print(f"Resource {self.name} closed")

# 测试
res = Resource("文件1")
res.open()
res.close()
# 程序结束或对象被垃圾回收时,__del__ 被调用

6.2 字符串表示

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    
    def __str__(self):
        """用户友好的字符串表示,str() 和 print() 调用"""
        return f"Person: {self.name}, {self.age} years old"
    
    def __repr__(self):
        """开发者友好的字符串表示,用于调试,repr() 调用"""
        return f"Person('{self.name}', {self.age})"
    
    def __format__(self, format_spec):
        """format() 函数调用"""
        if format_spec == "short":
            return f"{self.name[:3]}... ({self.age})"
        elif format_spec == "long":
            return f"{self.name} is {self.age} years old"
        else:
            return str(self)

# 测试
person = Person("Alice", 30)
print(str(person))  # Person: Alice, 30 years old
print(repr(person))  # Person('Alice', 30)
print(f"{person}")  # Person: Alice, 30 years old
print(f"{person:short}")  # Ali... (30)
print(f"{person:long}")  # Alice is 30 years old

6.3 比较运算符

class Student:
    def __init__(self, name, score):
        self.name = name
        self.score = score
    
    def __eq__(self, other):
        """== 运算符"""
        if isinstance(other, Student):
            return self.score == other.score
        return False
    
    def __ne__(self, other):
        """!= 运算符"""
        return not self.__eq__(other)
    
    def __lt__(self, other):
        """< 运算符"""
        if isinstance(other, Student):
            return self.score < other.score
        raise TypeError("不能比较不同类型")
    
    def __le__(self, other):
        """<= 运算符"""
        if isinstance(other, Student):
            return self.score <= other.score
        raise TypeError("不能比较不同类型")
    
    def __gt__(self, other):
        """> 运算符"""
        if isinstance(other, Student):
            return self.score > other.score
        raise TypeError("不能比较不同类型")
    
    def __ge__(self, other):
        """>= 运算符"""
        if isinstance(other, Student):
            return self.score >= other.score
        raise TypeError("不能比较不同类型")

# 测试
s1 = Student("Alice", 90)
s2 = Student("Bob", 85)
s3 = Student("Charlie", 90)

print(s1 == s2)  # False
print(s1 == s3)  # True
print(s1 != s2)  # True
print(s1 < s2)  # False
print(s1 > s2)  # True
print(s1 <= s3)  # True
print(s1 >= s3)  # True

6.4 数值运算

class Fraction:
    """分数类"""
    def __init__(self, numerator, denominator=1):
        if denominator == 0:
            raise ValueError("分母不能为0")
        self.numerator = numerator
        self.denominator = denominator
        self._simplify()
    
    def _simplify(self):
        """约分"""
        import math
        gcd = math.gcd(self.numerator, self.denominator)
        self.numerator //= gcd
        self.denominator //= gcd
    
    def __str__(self):
        return f"{self.numerator}/{self.denominator}"
    
    def __repr__(self):
        return f"Fraction({self.numerator}, {self.denominator})"
    
    def __add__(self, other):
        if isinstance(other, Fraction):
            new_num = (self.numerator * other.denominator + 
                      other.numerator * self.denominator)
            new_den = self.denominator * other.denominator
            return Fraction(new_num, new_den)
        raise TypeError("只能与 Fraction 相加")
    
    def __sub__(self, other):
        if isinstance(other, Fraction):
            new_num = (self.numerator * other.denominator - 
                      other.numerator * self.denominator)
            new_den = self.denominator * other.denominator
            return Fraction(new_num, new_den)
        raise TypeError("只能与 Fraction 相减")
    
    def __mul__(self, other):
        if isinstance(other, Fraction):
            new_num = self.numerator * other.numerator
            new_den = self.denominator * other.denominator
            return Fraction(new_num, new_den)
        raise TypeError("只能与 Fraction 相乘")
    
    def __truediv__(self, other):
        if isinstance(other, Fraction):
            new_num = self.numerator * other.denominator
            new_den = self.denominator * other.numerator
            return Fraction(new_num, new_den)
        raise TypeError("只能与 Fraction 相除")
    
    def __float__(self):
        """转换为浮点数"""
        return self.numerator / self.denominator
    
    def __int__(self):
        """转换为整数(向下取整)"""
        return self.numerator // self.denominator

# 测试
f1 = Fraction(1, 2)
f2 = Fraction(1, 3)

print(f1 + f2)  # 5/6
print(f1 - f2)  # 1/6
print(f1 * f2)  # 1/6
print(f1 / f2)  # 3/2
print(float(f1))  # 0.5
print(int(f1))  # 0

6.5 容器类型模拟

class Playlist:
    """播放列表,模拟列表行为"""
    def __init__(self, *songs):
        self.songs = list(songs)
    
    def __len__(self):
        """返回歌曲数量"""
        return len(self.songs)
    
    def __getitem__(self, index):
        """索引访问"""
        return self.songs[index]
    
    def __setitem__(self, index, value):
        """设置索引处的值"""
        self.songs[index] = value
    
    def __delitem__(self, index):
        """删除索引处的值"""
        del self.songs[index]
    
    def __contains__(self, item):
        """in 运算符"""
        return item in self.songs
    
    def __iter__(self):
        """迭代器"""
        return iter(self.songs)
    
    def __reversed__(self):
        """reversed() 函数"""
        return reversed(self.songs)
    
    def append(self, song):
        self.songs.append(song)
    
    def __str__(self):
        return "\n".join(f"{i+1}. {song}" for i, song in enumerate(self.songs))

# 测试
playlist = Playlist("Song1", "Song2", "Song3")
playlist.append("Song4")

print(f"播放列表长度: {len(playlist)}")  # 4
print(f"第一首歌: {playlist[0]}")  # Song1
print(f"包含 Song2: {'Song2' in playlist}")  # True

playlist[1] = "New Song"
print("\n修改后的播放列表:")
print(playlist)

print("\n反向迭代:")
for song in reversed(playlist):
    print(song)

七、类装饰器与元类

7.1 类装饰器

def add_method(cls):
    """类装饰器:为类添加新方法"""
    def hello(self):
        return f"Hello from {self.__class__.__name__}"
    
    def goodbye(self):
        return f"Goodbye from {self.__class__.__name__}"
    
    # 动态添加方法
    cls.hello = hello
    cls.goodbye = goodbye
    return cls

def add_attribute(name, value):
    """带参数的类装饰器:为类添加属性"""
    def decorator(cls):
        setattr(cls, name, value)
        return cls
    return decorator

@add_method
@add_attribute("version", "1.0")
class MyClass:
    def __init__(self, name):
        self.name = name

# 测试
obj = MyClass("Test")
print(obj.hello())  # Hello from MyClass
print(obj.goodbye())  # Goodbye from MyClass
print(MyClass.version)  # 1.0

7.2 属性装饰器高级用法

class CachedProperty:
    """属性装饰器:缓存计算结果"""
    def __init__(self, func):
        self.func = func
        self.cache_name = f"_cache_{func.__name__}"
    
    def __get__(self, obj, objtype=None):
        if obj is None:
            return self
        if not hasattr(obj, self.cache_name):
            value = self.func(obj)
            setattr(obj, self.cache_name, value)
        return getattr(obj, self.cache_name)

class DataProcessor:
    def __init__(self, data):
        self.data = data
    
    @CachedProperty
    def processed_data(self):
        """耗时计算,结果会被缓存"""
        print("Processing data...")
        # 模拟耗时计算
        result = [x * 2 for x in self.data]
        return result

# 测试
processor = DataProcessor([1, 2, 3, 4, 5])
print(processor.processed_data)  # Processing data... 然后输出 [2, 4, 6, 8, 10]
print(processor.processed_data)  # 直接输出 [2, 4, 6, 8, 10],不再计算

7.3 描述符

  • 控制属性访问__get__, __set__, __delete__
  • 应用场景:类型检查、数据验证、惰性计算
class TypedAttribute:
    """类型检查描述符"""
    def __init__(self, name, expected_type):
        self.name = name
        self.expected_type = expected_type
    
    def __get__(self, obj, objtype=None):
        if obj is None:
            return self
        return obj.__dict__.get(self.name)
    
    def __set__(self, obj, value):
        if not isinstance(value, self.expected_type):
            raise TypeError(f"{self.name} 必须是 {self.expected_type.__name__} 类型")
        obj.__dict__[self.name] = value
    
    def __delete__(self, obj):
        del obj.__dict__[self.name]

class PositiveNumber:
    """正数描述符"""
    def __init__(self, name):
        self.name = name
    
    def __get__(self, obj, objtype=None):
        if obj is None:
            return self
        return obj.__dict__.get(self.name)
    
    def __set__(self, obj, value):
        if not isinstance(value, (int, float)):
            raise TypeError(f"{self.name} 必须是数字")
        if value <= 0:
            raise ValueError(f"{self.name} 必须是正数")
        obj.__dict__[self.name] = value

class Person:
    # 使用描述符
    name = TypedAttribute("name", str)
    age = TypedAttribute("age", int)
    salary = PositiveNumber("salary")
    
    def __init__(self, name, age, salary):
        self.name = name
        self.age = age
        self.salary = salary

# 测试
person = Person("Alice", 30, 50000)
print(person.name, person.age, person.salary)  # Alice 30 50000

try:
    person.name = 123  # TypeError: name 必须是 str 类型
except TypeError as e:
    print(f"错误: {e}")

try:
    person.salary = -1000  # ValueError: salary 必须是正数
except ValueError as e:
    print(f"错误: {e}")

7.4 元类

  • 类的类:控制类的创建行为
  • type:所有类的元类
  • __metaclass__:指定元类
class SingletonMeta(type):
    """单例元类"""
    _instances = {}
    
    def __call__(cls, *args, **kwargs):
        if cls not in cls._instances:
            instance = super().__call__(*args, **kwargs)
            cls._instances[cls] = instance
        return cls._instances[cls]

class Logger(metaclass=SingletonMeta):
    """单例类:日志记录器"""
    def __init__(self, name="Default"):
        self.name = name
        self.logs = []
    
    def log(self, message):
        self.logs.append(message)
    
    def show_logs(self):
        for log in self.logs:
            print(f"[{self.name}] {log}")

# 测试
logger1 = Logger("App")
logger2 = Logger("Another")  # 这个名称会被忽略

logger1.log("第一条日志")
logger2.log("第二条日志")

print(logger1 is logger2)  # True
logger1.show_logs()
# 输出:
# [App] 第一条日志
# [App] 第二条日志

八、设计模式

8.1 工厂模式

from enum import Enum

class VehicleType(Enum):
    CAR = "car"
    TRUCK = "truck"
    MOTORCYCLE = "motorcycle"

class Vehicle:
    def drive(self):
        pass

class Car(Vehicle):
    def drive(self):
        return "Driving a car"

class Truck(Vehicle):
    def drive(self):
        return "Driving a truck"

class Motorcycle(Vehicle):
    def drive(self):
        return "Riding a motorcycle"

class VehicleFactory:
    """工厂类"""
    @staticmethod
    def create_vehicle(vehicle_type):
        if vehicle_type == VehicleType.CAR:
            return Car()
        elif vehicle_type == VehicleType.TRUCK:
            return Truck()
        elif vehicle_type == VehicleType.MOTORCYCLE:
            return Motorcycle()
        else:
            raise ValueError(f"未知的车辆类型: {vehicle_type}")

# 使用工厂
car = VehicleFactory.create_vehicle(VehicleType.CAR)
truck = VehicleFactory.create_vehicle(VehicleType.TRUCK)

print(car.drive())  # Driving a car
print(truck.drive())  # Driving a truck

8.2 观察者模式

class Observer:
    """观察者接口"""
    def update(self, message):
        pass

class Subject:
    """主题(被观察者)"""
    def __init__(self):
        self._observers = []
    
    def attach(self, observer):
        """添加观察者"""
        if observer not in self._observers:
            self._observers.append(observer)
    
    def detach(self, observer):
        """移除观察者"""
        self._observers.remove(observer)
    
    def notify(self, message):
        """通知所有观察者"""
        for observer in self._observers:
            observer.update(message)

class EmailNotifier(Observer):
    """邮件通知器"""
    def update(self, message):
        print(f"发送邮件: {message}")

class SMSNotifier(Observer):
    """短信通知器"""
    def update(self, message):
        print(f"发送短信: {message}")

class AppNotifier(Observer):
    """应用通知器"""
    def update(self, message):
        print(f"应用通知: {message}")

# 测试
weather_station = Subject()

email_notifier = EmailNotifier()
sms_notifier = SMSNotifier()
app_notifier = AppNotifier()

weather_station.attach(email_notifier)
weather_station.attach(sms_notifier)
weather_station.attach(app_notifier)

weather_station.notify("温度: 25°C")
# 输出:
# 发送邮件: 温度: 25°C
# 发送短信: 温度: 25°C
# 应用通知: 温度: 25°C

weather_station.detach(sms_notifier)
weather_station.notify("湿度: 60%")
# 输出:
# 发送邮件: 湿度: 60%
# 应用通知: 湿度: 60%

8.3 策略模式

from abc import ABC, abstractmethod

class PaymentStrategy(ABC):
    """支付策略接口"""
    @abstractmethod
    def pay(self, amount):
        pass

class CreditCardPayment(PaymentStrategy):
    """信用卡支付"""
    def __init__(self, card_number, cvv):
        self.card_number = card_number
        self.cvv = cvv
    
    def pay(self, amount):
        return f"信用卡支付 {amount} 元,卡号: {self.card_number[-4:]}"

class PayPalPayment(PaymentStrategy):
    """PayPal支付"""
    def __init__(self, email):
        self.email = email
    
    def pay(self, amount):
        return f"PayPal支付 {amount} 元,邮箱: {self.email}"

class BitcoinPayment(PaymentStrategy):
    """比特币支付"""
    def __init__(self, wallet_address):
        self.wallet_address = wallet_address
    
    def pay(self, amount):
        return f"比特币支付 {amount} 元,钱包地址: {self.wallet_address[:8]}..."

class ShoppingCart:
    """购物车"""
    def __init__(self):
        self.items = []
        self.payment_strategy = None
    
    def add_item(self, item, price):
        self.items.append((item, price))
    
    def set_payment_strategy(self, strategy):
        self.payment_strategy = strategy
    
    def checkout(self):
        if not self.payment_strategy:
            raise ValueError("未设置支付方式")
        
        total = sum(price for _, price in self.items)
        return self.payment_strategy.pay(total)

# 测试
cart = ShoppingCart()
cart.add_item("笔记本电脑", 7999)
cart.add_item("鼠标", 199)

# 使用信用卡支付
cart.set_payment_strategy(CreditCardPayment("1234-5678-9012-3456", "123"))
print(cart.checkout())  # 信用卡支付 8198 元,卡号: 3456

# 切换支付方式
cart.set_payment_strategy(PayPalPayment("user@example.com"))
print(cart.checkout())  # PayPal支付 8198 元,邮箱: user@example.com

8.4 装饰器模式

class Coffee:
    """咖啡接口"""
    def get_cost(self):
        pass
    
    def get_description(self):
        pass

class SimpleCoffee(Coffee):
    """简单咖啡"""
    def get_cost(self):
        return 5
    
    def get_description(self):
        return "Simple coffee"

class CoffeeDecorator(Coffee):
    """咖啡装饰器基类"""
    def __init__(self, coffee):
        self._coffee = coffee
    
    def get_cost(self):
        return self._coffee.get_cost()
    
    def get_description(self):
        return self._coffee.get_description()

class MilkDecorator(CoffeeDecorator):
    """牛奶装饰器"""
    def get_cost(self):
        return self._coffee.get_cost() + 2
    
    def get_description(self):
        return self._coffee.get_description() + ", milk"

class SugarDecorator(CoffeeDecorator):
    """糖装饰器"""
    def get_cost(self):
        return self._coffee.get_cost() + 1
    
    def get_description(self):
        return self._coffee.get_description() + ", sugar"

class WhippedCreamDecorator(CoffeeDecorator):
    """奶油装饰器"""
    def get_cost(self):
        return self._coffee.get_cost() + 3
    
    def get_description(self):
        return self._coffee.get_description() + ", whipped cream"

# 测试
coffee = SimpleCoffee()
print(f"{coffee.get_description()}: ${coffee.get_cost()}")  # Simple coffee: $5

# 加牛奶
coffee_with_milk = MilkDecorator(coffee)
print(f"{coffee_with_milk.get_description()}: ${coffee_with_milk.get_cost()}")  # Simple coffee, milk: $7

# 加牛奶和糖
coffee_with_milk_sugar = SugarDecorator(coffee_with_milk)
print(f"{coffee_with_milk_sugar.get_description()}: ${coffee_with_milk_sugar.get_cost()}")  # Simple coffee, milk, sugar: $8

# 加牛奶、糖和奶油
coffee_deluxe = WhippedCreamDecorator(coffee_with_milk_sugar)
print(f"{coffee_deluxe.get_description()}: ${coffee_deluxe.get_cost()}")  # Simple coffee, milk, sugar, whipped cream: $11

九、高级主题

9.1 混入类

  • 多重继承的特殊用法
  • 提供特定功能,不用于创建实例
class JSONMixin:
    """JSON混入类"""
    def to_json(self):
        import json
        return json.dumps(self.__dict__, indent=2)
    
    @classmethod
    def from_json(cls, json_str):
        import json
        data = json.loads(json_str)
        return cls(**data)

class XMLMixin:
    """XML混入类"""
    def to_xml(self):
        import xml.etree.ElementTree as ET
        root = ET.Element(self.__class__.__name__)
        for key, value in self.__dict__.items():
            child = ET.SubElement(root, key)
            child.text = str(value)
        return ET.tostring(root, encoding='unicode')

class LoggableMixin:
    """日志混入类"""
    def log(self, message):
        print(f"[{self.__class__.__name__}] {message}")

class Person(JSONMixin, XMLMixin, LoggableMixin):
    def __init__(self, name, age, city):
        self.name = name
        self.age = age
        self.city = city

# 测试
person = Person("Alice", 30, "New York")
person.log("对象已创建")  # [Person] 对象已创建

json_str = person.to_json()
print("JSON格式:")
print(json_str)

xml_str = person.to_xml()
print("\nXML格式:")
print(xml_str)

# 从JSON恢复对象
person2 = Person.from_json(json_str)
print(f"\n恢复的对象: {person2.name}, {person2.age}, {person2.city}")

9.2 数据类

  • Python 3.7+ 新增特性
  • 简化类的创建,自动生成特殊方法
from dataclasses import dataclass, field, asdict, astuple
from typing import List, ClassVar
from datetime import datetime

@dataclass(order=True, frozen=False)
class Product:
    """数据类:产品"""
    # 实例属性
    name: str
    price: float
    tags: List[str] = field(default_factory=list)
    created_at: datetime = field(default_factory=datetime.now)
    
    # 类属性
    currency: ClassVar[str] = "USD"
    
    def get_price_with_currency(self):
        return f"{self.currency} {self.price:.2f}"

# 测试
product1 = Product("Laptop", 999.99, ["electronics", "computers"])
product2 = Product("Mouse", 29.99, ["electronics", "accessories"])
product3 = Product("Laptop", 999.99, ["electronics", "computers"])

print(product1)  # Product(name='Laptop', price=999.99, tags=['electronics', 'computers'], ...)
print(product1 == product3)  # True
print(product1.get_price_with_currency())  # USD 999.99

# 转换为字典
print(asdict(product1))

# 转换为元组
print(astuple(product1))

# 排序(因为设置了 order=True)
products = [product2, product1]
print(sorted(products))  # 按名称和价格排序

9.3 枚举类

from enum import Enum, IntEnum, auto, unique

@unique
class Color(Enum):
    """颜色枚举"""
    RED = 1
    GREEN = 2
    BLUE = 3
    YELLOW = 4

class Status(IntEnum):
    """状态枚举(整数枚举)"""
    PENDING = auto()  # 1
    PROCESSING = auto()  # 2
    COMPLETED = auto()  # 3
    FAILED = auto()  # 4

class Direction(Enum):
    """方向枚举(带值)"""
    NORTH = (0, 1)
    SOUTH = (0, -1)
    EAST = (1, 0)
    WEST = (-1, 0)
    
    def __init__(self, dx, dy):
        self.dx = dx
        self.dy = dy
    
    def move(self, x, y, distance=1):
        return x + self.dx * distance, y + self.dy * distance

# 测试
color = Color.RED
print(color)  # Color.RED
print(color.name)  # RED
print(color.value)  # 1
print(list(Color))  # [<Color.RED: 1>, <Color.GREEN: 2>, ...]

status = Status.PROCESSING
print(status)  # Status.PROCESSING
print(status.value)  # 2

direction = Direction.NORTH
x, y = 0, 0
new_x, new_y = direction.move(x, y, 5)
print(f"从({x},{y})向{direction.name}移动5个单位: ({new_x},{new_y})")  # (0,5)

9.4 命名元组

from collections import namedtuple
from typing import NamedTuple

# 方式1: collections.namedtuple
Point = namedtuple('Point', ['x', 'y'])
p1 = Point(10, 20)
print(p1.x, p1.y)  # 10 20
print(p1[0], p1[1])  # 10 20

# 方式2: typing.NamedTuple(支持类型注解)
class Employee(NamedTuple):
    name: str
    age: int
    department: str = "Engineering"
    
    def get_info(self):
        return f"{self.name}, {self.age}, {self.department}"

emp = Employee("Alice", 30)
print(emp)  # Employee(name='Alice', age=30, department='Engineering')
print(emp.get_info())  # Alice, 30, Engineering
print(emp._asdict())  # {'name': 'Alice', 'age': 30, 'department': 'Engineering'}

# 创建新实例,修改部分字段
emp_new = emp._replace(age=31, department="Sales")
print(emp_new)  # Employee(name='Alice', age=31, department='Sales')

9.5 抽象基类高级用法

from abc import ABC, abstractmethod, abstractproperty
from collections.abc import Sequence, Sized

class CustomList(Sequence, Sized):
    """自定义列表,实现Sequence和Sized接口"""
    def __init__(self, *args):
        self._data = list(args)
    
    def __getitem__(self, index):
        return self._data[index]
    
    def __len__(self):
        return len(self._data)
    
    def __str__(self):
        return str(self._data)

# 测试
my_list = CustomList(1, 2, 3, 4, 5)
print(my_list)  # [1, 2, 3, 4, 5]
print(len(my_list))  # 5
print(my_list[2])  # 3
print(3 in my_list)  # True
print(list(my_list))  # [1, 2, 3, 4, 5]

# 检查是否实现了接口
print(isinstance(my_list, Sequence))  # True
print(isinstance(my_list, Sized))  # True

十、最佳实践

10.1 类设计原则

  1. 组合优于继承:尽量使用组合而不是继承
  2. 接口隔离:定义小而专一的接口
  3. 依赖抽象:依赖接口而不是具体实现
  4. 最少知识原则:减少对象之间的耦合
  5. 单一职责:一个类只做一件事

10.2 代码组织

  1. 模块化:将相关类放在同一模块
  2. 包结构:使用包组织相关模块
  3. 导入规范:避免循环导入
  4. 文档字符串:为类和方法添加文档
  5. 类型注解:使用类型提示提高代码可读性

10.3 性能考虑

  1. __slots__:减少内存使用
  2. 属性缓存:缓存计算结果
  3. 惰性加载:延迟初始化
  4. 对象池:复用对象减少创建开销
class OptimizedClass:
    """使用__slots__优化内存"""
    __slots__ = ['x', 'y', 'z']  # 固定属性列表
    
    def __init__(self, x, y, z):
        self.x = x
        self.y = y
        self.z = z
    
    def __str__(self):
        return f"({self.x}, {self.y}, {self.z})"

# 测试
obj = OptimizedClass(1, 2, 3)
print(obj)  # (1, 2, 3)
# obj.new_attr = 4  # 错误:不能添加新属性

10.4 测试策略

  1. 单元测试:测试单个类和方法
  2. 集成测试:测试类之间的协作
  3. Mock对象:模拟依赖对象
  4. 测试夹具:重用测试数据
  5. 覆盖率:确保代码覆盖

10.5 调试技巧

  1. __repr__:提供详细的调试信息
  2. 日志记录:记录对象状态变化
  3. 断言:验证对象状态
  4. 调试器:使用pdb进行交互式调试
  5. 属性检查:验证对象完整性

十一、学习资源

11.1 官方文档

  • Python官方文档:类和对象相关章节
  • PEP文档:PEP 3119(抽象基类)、PEP 557(数据类)等
  • 标准库文档:abc、collections、dataclasses等模块

11.2 推荐书籍

  1. 《Python高级编程》:面向对象高级特性
  2. 《流畅的Python》:深入讲解Python面向对象
  3. 《设计模式:可复用面向对象软件的基础》:经典设计模式
  4. 《Python Cookbook》:实用编程技巧

11.3 在线资源

  • Real Python:面向对象编程教程
  • Python官方教程:类和对象基础
  • Stack Overflow:问题解答
  • GitHub:开源项目代码学习

11.4 练习项目

  1. 游戏开发:角色、道具、场景类设计
  2. Web框架:模拟Flask/Django的MVC结构
  3. GUI应用:使用面向对象设计界面
  4. 数据处理:设计数据管道和处理类
  5. 网络爬虫:设计爬虫框架和组件

11.5 进阶方向

  1. 元编程:深入理解Python对象模型
  2. 设计模式:掌握更多设计模式
  3. 架构设计:大型系统面向对象设计
  4. 并发编程:面向对象与并发结合
  5. 函数式编程:与面向对象结合使用