引言

面向对象编程(Object-Oriented Programming, OOP)是现代软件开发的核心范式之一。在Python中,OOP不仅提供了强大的代码组织能力,还通过封装、继承和多态等特性,帮助开发者构建可维护、可扩展的应用程序。本文将深入探讨Python中OOP的核心概念、高级特性以及实际应用,帮助读者从基础理解到高级实践。

1. 类与对象的基础

1.1 类的定义与实例化

在Python中,类是创建对象的蓝图。它定义了对象的属性和方法。以下是一个简单的类定义示例:

class Dog:
    # 类属性(所有实例共享)
    species = "Canis familiaris"
    
    def __init__(self, name, age):
        # 实例属性(每个实例独有)
        self.name = name
        self.age = age
    
    def bark(self):
        return f"{self.name} says woof!"
    
    def describe(self):
        return f"{self.name} is {self.age} years old"

# 创建实例
dog1 = Dog("Buddy", 3)
dog2 = Dog("Max", 5)

print(dog1.bark())  # Buddy says woof!
print(dog2.describe())  # Max is 5 years old
print(Dog.species)  # Canis familiaris

关键点:

  • __init__ 方法是构造函数,在创建实例时自动调用
  • self 参数指向实例本身
  • 类属性被所有实例共享,实例属性每个实例独有

1.2 实例方法、类方法与静态方法

Python提供了三种方法类型,各有不同的用途:

class Calculator:
    # 实例方法 - 操作实例数据
    def __init__(self):
        self.result = 0
    
    def add(self, x):
        self.result += x
        return self.result
    
    # 类方法 - 操作类数据(使用cls)
    @classmethod
    def get_description(cls):
        return f"This is a {cls.__name__} class"
    
    # 静态方法 - 独立于类和实例
    @staticmethod
    def multiply(x, y):
        return x * y

# 使用示例
calc = Calculator()
print(calc.add(5))  # 5
print(Calculator.get_description())  # This is a Calculator class
print(Calculator.multiply(3, 4))  # 12

方法类型对比:

方法类型 装饰器 第一个参数 访问权限
实例方法 self 可访问实例和类属性
类方法 @classmethod cls 只能访问类属性
静态方法 @staticmethod 不能访问实例或类属性

2. 封装与访问控制

2.1 Python的访问控制机制

Python通过命名约定实现访问控制,而不是严格的私有化:

class BankAccount:
    def __init__(self, account_holder, initial_balance):
        self.account_holder = account_holder  # 公共属性
        self._balance = initial_balance       # 受保护属性(约定)
        self.__pin = "1234"                   # 私有属性(名称修饰)
    
    # 公共方法
    def get_balance(self):
        return self._balance
    
    # 私有方法
    def __verify_pin(self, pin):
        return pin == self.__pin
    
    def withdraw(self, amount, pin):
        if self.__verify_pin(pin):
            if amount <= self._balance:
                self._balance -= amount
                return f"Withdrew {amount}. New balance: {self._balance}"
            return "Insufficient funds"
        return "Invalid PIN"

# 使用示例
account = BankAccount("Alice", 1000)
print(account.account_holder)  # Alice - 公共属性可访问
print(account._balance)        # 1000 - 约定保护,但技术上可访问
# print(account.__pin)         # AttributeError - 私有属性不可直接访问
# print(account.__verify_pin("1234"))  # AttributeError - 私有方法不可直接访问

print(account.withdraw(200, "1234"))  # Withdrew 200. New balance: 1000
print(account.withdraw(100, "9999"))  # Invalid PIN

Python名称修饰机制:

# Python解释器会将私有名称转换为:_类名__属性名
print(account._BankAccount__pin)  # '1234' - 可以这样访问,但不推荐

2.2 使用property装饰器实现真正的封装

class Temperature:
    def __init__(self, celsius):
        self._celsius = celsius
    
    @property
    def celsius(self):
        """获取摄氏温度"""
        return self._celsius
    
    @celsius.setter
    def celsius(self, value):
        """设置摄氏温度并验证"""
        if value < -273.15:
            raise ValueError("Temperature below absolute zero is impossible")
        self._celsius = value
    
    @property
    def fahrenheit(self):
        """计算华氏温度"""
        return (self._celsius * 9/5) + 32
    
    @fahrenheit.setter
    def fahrenheit(self, value):
        """通过华氏温度设置"""
        self.celsius = (value - 32) * 5/9  # 使用celsius setter进行验证

# 使用示例
temp = Temperature(25)
print(temp.celsius)      # 25
print(temp.fahrenheit)   # 77.0

temp.celsius = 30
print(temp.fahrenheit)   # 86.0

temp.fahrenheit = 100
print(temp.celsius)      # 37.77777777777778

# 验证失败
try:
    temp.celsius = -300
except ValueError as e:
    print(e)  # Temperature below absolute zero is impossible

3. 继承与多态

3.1 单继承与方法重写

class Animal:
    def __init__(self, name, species):
        self.name = name
        self.species = species
    
    def speak(self):
        raise NotImplementedError("Subclasses must implement speak method")
    
    def describe(self):
        return f"{self.name} is a {self.species}"

class Cat(Animal):
    def __init__(self, name, indoor=True):
        super().__init__(name, "Felis catus")
        self.indoor = indoor
    
    def speak(self):
        return "Meow"
    
    def describe(self):
        # 重写父类方法并扩展功能
        base_desc = super().describe()
        location = "indoor" if self.indoor else "outdoor"
        return f"{base_desc} ({location})"

class Dog(Animal):
    def __init__(self, name, breed):
        super().__init__(name, "Canis familiaris")
        self.breed = breed
    
    def speak(self):
        return "Woof!"
    
    def fetch(self, item):
        return f"{self.name} fetched {item}"

# 使用示例
animals = [
    Cat("Whiskers"),
    Dog("Buddy", "Golden Retriever"),
    Cat("Mittens", indoor=False)
]

for animal in animals:
    print(f"{animal.name}: {animal.speak()}")
    print(f"  {animal.describe()}")
    if isinstance(animal, Dog):
        print(f"  {animal.fetch('ball')}")

3.2 多继承与MRO(方法解析顺序)

Python支持多继承,使用C3线性化算法确定方法解析顺序:

class Flyer:
    def __init__(self, name):
        self.name = name
    
    def fly(self):
        return f"{self.name} is flying"

class Swimmer:
    def __init__(self, name):
        self.name = name
    
    def swim(self):
        return f"{self.name} is swimming"

class FlyingFish(Flyer, Swimmer):
    def __init__(self, name):
        # 注意:两个父类都有__init__,需要明确调用
        Flyer.__init__(self, name)
        # Swimmer.__init__(self, name)  # 如果调用会重复初始化name
    
    def describe(self):
        return f"{self.name} can both fly and swim"

# 使用示例
fish = FlyingFish("Swift")
print(fish.fly())    # Swift is flying
print(fish.swim())   # Swift is swimming
print(fish.describe())  # Swift can both fly and swim

# 查看MRO
print(FlyingFish.mro())
# [<class '__main__.FlyingFish'>, <class '__main__.Flyer'>, <class '__main__.Swimmer'>, <class 'object'>]

MRO冲突解决:

class A:
    def method(self):
        return "A"

class B(A):
    def method(self):
        return "B"

class C(A):
    def method(self):
        return "C"

class D(B, C):
    pass

# D的MRO: D -> B -> C -> A -> object
print(D.mro())  # [<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]

d = D()
print(d.method())  # "B" - 按照MRO顺序找到第一个method

4. 高级OOP特性

4.1 抽象基类(ABC)

from abc import ABC, abstractmethod
import numbers

class Shape(ABC):
    @abstractmethod
    def area(self):
        """计算面积"""
        pass
    
    @abstractmethod
    def perimeter(self):
        """计算周长"""
        pass
    
    def describe(self):
        return f"Area: {self.area():.2f}, Perimeter: {self.perimeter():.2f}"

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(5, 3), Circle(4)]

for shape in shapes:
    print(shape.describe())

# 尝试实例化未实现抽象方法的类会失败
try:
    class BadShape(Shape):
        pass
    bad = BadShape()
except TypeError as e:
    print(f"Error: {e}")  # Can't instantiate abstract class BadShape...

4.2 魔术方法(Dunder Methods)

class Vector2D:
    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"Vector2D({self.x}, {y})"
    
    # 算术运算
    def __add__(self, other):
        if isinstance(other, Vector2D):
            return Vector2D(self.x + other.x, self.y + other.y)
        return NotImplemented
    
    def __sub__(self, other):
        if isinstance(other, Vector2D):
            return Vector2D(self.x - other.x, self.y - other.y)
        return NotImplemented
    
    def __mul__(self, scalar):
        if isinstance(scalar, (int, float)):
            return Vector2D(self.x * scalar, self.y * scalar)
        return NotImplemented
    
    def __rmul__(self, scalar):
        return self.__mul__(scalar)
    
    # 比较运算
    def __eq__(self, other):
        if isinstance(other, Vector2D):
            return self.x == other.x and self.y == other.y
        return False
    
    def __lt__(self, other):
        if isinstance(other, Vector2D):
            return (self.x**2 + self.y**2) < (other.x**2 + other.y**2)
        return NotImplemented
    
    # 容器协议
    def __len__(self):
        return 2
    
    def __getitem__(self, key):
        if key == 0:
            return self.x
        elif key == 1:
            return self.y
        raise IndexError("Vector2D index out of range")
    
    def __iter__(self):
        return iter([self.x, self.y])
    
    # 可调用对象
    def __call__(self, other=None):
        if other is None:
            return self
        return self.__mul__(other)

# 使用示例
v1 = Vector2D(3, 4)
v2 = Vector2D(1, 2)

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

4.3 描述符(Descriptors)

描述符是实现了描述符协议的对象,用于控制属性访问:

class TypedProperty:
    """类型检查属性描述符"""
    def __init__(self, name, expected_type, default=None):
        self.name = "_" + name
        self.expected_type = expected_type
        self.default = default
    
    def __get__(self, instance, owner):
        if instance is None:
            return self
        return getattr(instance, self.name, self.default)
    
    def __set__(self, instance, value):
        if not isinstance(value, self.expected_type):
            raise TypeError(f"{self.name} must be of type {self.expected_type}")
        setattr(instance, self.name, value)
    
    def __delete__(self, instance):
        raise AttributeError(f"Cannot delete {self.name}")

class Product:
    # 使用描述符定义属性
    name = TypedProperty("name", str)
    price = TypedProperty("price", (int, float), default=0.0)
    quantity = TypedProperty("quantity", int, default=0)
    
    def __init__(self, name, price, quantity):
        self.name = name
        self.price = price
        self.quantity = quantity
    
    def total_cost(self):
        return self.price * self.quantity

# 使用示例
product = Product("Laptop", 999.99, 5)
print(product.name)      # Laptop
print(product.price)     # 999.99
print(product.total_cost())  # 4999.95

# 类型检查
try:
    product.price = "expensive"
except TypeError as e:
    print(e)  # _price must be of type (<class 'int'>, <class 'float'>)

try:
    bad_product = Product(123, 100, 5)  # name必须是str
except TypeError as e:
    print(e)  # _name must be of type <class 'str'>

# 删除属性会失败
try:
    del product.price
except AttributeError as e:
    print(e)  # Cannot delete _price

5. 设计模式在Python OOP中的应用

5.1 工厂模式

from abc import ABC, abstractmethod

class PaymentProcessor(ABC):
    @abstractmethod
    def process_payment(self, amount):
        pass

class CreditCardProcessor(PaymentProcessor):
    def __init__(self, card_number):
        self.card_number = card_number
    
    def process_payment(self, amount):
        return f"Processing ${amount} via Credit Card {self.card_number[-4:]}"

class PayPalProcessor(PaymentProcessor):
    def __init__(self, email):
        self.email = email
    
    def process_payment(self, amount):
        return f"Processing ${amount} via PayPal account {self.email}"

class CryptoProcessor(PaymentProcessor):
    def __init__(self, wallet_address):
        self.wallet_address = wallet_address
    
    def process_payment(self, amount):
        return f"Processing ${amount} via Crypto wallet {self.wallet_address[:8]}..."

class PaymentProcessorFactory:
    """工厂类创建支付处理器"""
    @staticmethod
    def create_processor(payment_type, **kwargs):
        processors = {
            'credit_card': CreditCardProcessor,
            'paypal': PayPalProcessor,
            'crypto': CryptoProcessor
        }
        
        if payment_type not in processors:
            raise ValueError(f"Unknown payment type: {payment_type}")
        
        return processors[payment_type](**kwargs)

# 使用示例
factory = PaymentProcessorFactory

# 创建不同的支付处理器
processor1 = factory.create_processor('credit_card', card_number="1234-5678-9012-3456")
processor2 = factory.create_processor('paypal', email="user@example.com")
processor3 = factory.create_processor('crypto', wallet_address="0x1234567890abcdef")

print(processor1.process_payment(100))  # Processing $100 via Credit Card 3456
print(processor2.process_payment(50))   # Processing $50 via PayPal account user@example.com
print(processor3.process_payment(200))  # Processing $200 via Crypto wallet 0x123456...

5.2 观察者模式

class Subject:
    """被观察的对象"""
    def __init__(self):
        self._observers = []
        self._state = None
    
    def attach(self, observer):
        if observer not in self._observers:
            self._observers.append(observer)
    
    def detach(self, observer):
        try:
            self._observers.remove(observer)
        except ValueError:
            pass
    
    def notify(self):
        for observer in self._observers:
            observer.update(self._state)
    
    def update_state(self, new_state):
        self._state = new_state
        self.notify()

class Observer(ABC):
    @abstractmethod
    def update(self, state):
        pass

class EmailNotifier(Observer):
    def update(self, state):
        print(f"Email: System state changed to {state}")

class SMSNotifier(Observer):
    def update(self, state):
        print(f"SMS: System state changed to {state}")

class LogNotifier(Observer):
    def update(self, state):
        print(f"Log: System state changed to {state}")

# 使用示例
subject = Subject()

email_notifier = EmailNotifier()
sms_notifier = SMSNotifier()
log_notifier = LogNotifier()

subject.attach(email_notifier)
subject.attach(sms_notifier)
subject.attach(log_notifier)

print("=== State changed to 'ERROR' ===")
subject.update_state("ERROR")

print("\n=== Detach SMS, state changed to 'OK' ===")
subject.detach(sms_notifier)
subject.update_state("OK")

6. Python OOP最佳实践

6.1 组合优于继承原则

# 不好的设计:过度使用继承
class Employee:
    def __init__(self, name, salary):
        self.name = name
        self.salary = salary

class Manager(Employee):
    def __init__(self, name, salary, department):
        super().__init__(name, salary)
        self.department = department
    
    def schedule_meeting(self):
        return f"Manager {self.name} schedules meeting"

class Developer(Employee):
    def __init__(self, name, salary, language):
        super().__init__(name, salary)
        self.language = language
    
    def write_code(self):
        return f"Developer {self.name} writes {self.language} code"

# 更好的设计:使用组合
class Role:
    def __init__(self, role_name):
        self.role_name = role_name
    
    def perform_duties(self):
        return f"Performing duties of {self.role_name}"

class ManagerRole(Role):
    def __init__(self, department):
        super().__init__("Manager")
        self.department = department
    
    def perform_duties(self):
        return f"Managing department {self.department}"

class DeveloperRole(Role):
    def __init__(self, language):
        super().__init__("Developer")
        self.language = language
    
    def perform_duties(self):
        return f"Writing {self.language} code"

class Employee:
    def __init__(self, name, salary, role):
        self.name = name
        self.salary = salary
        self.role = role
    
    def do_work(self):
        return f"{self.name} ({self.role.role_name}): {self.role.perform_duties()}"

# 使用组合的灵活性
manager = Employee("Alice", 80000, ManagerRole("Engineering"))
developer = Employee("Bob", 60000, DeveloperRole("Python"))

print(manager.do_work())    # Alice (Manager): Managing department Engineering
print(developer.do_work())  # Bob (Developer): Writing Python code

# 可以轻松改变角色
developer.role = ManagerRole("Sales")
print(developer.do_work())  # Bob (Manager): Managing department Sales

6.2 使用dataclass简化代码

from dataclasses import dataclass, field
from typing import List

@dataclass
class Student:
    name: str
    student_id: int
    grades: List[float] = field(default_factory=list)
    
    def add_grade(self, grade: float):
        self.grades.append(grade)
    
    def average(self):
        return sum(self.grades) / len(self.grades) if self.grades else 0
    
    def __str__(self):
        return f"Student {self.name} (ID: {self.student_id}) - Avg: {self.average():.2f}"

# 使用示例
student1 = Student("Charlie", 1001)
student1.add_grade(85)
student1.add_grade(92)
student1.add_grade(78)

student2 = Student("Diana", 1002, [95, 88, 91])

print(student1)  # Student Charlie (ID: 1001) - Avg: 85.00
print(student2)  # Student Diana (ID: 1002) - Avg: 91.33

# 自动生成的比较方法
print(student1 == Student("Charlie", 1001, [85, 92, 78]))  # True

7. 异常处理与OOP

7.1 自定义异常类

class InsufficientFundsError(Exception):
    """当账户余额不足时抛出"""
    def __init__(self, balance, amount):
        self.balance = balance
        self.amount = amount
        super().__init__(f"Insufficient funds: balance={balance}, attempted={amount}")

class InvalidAccountError(Exception):
    """当账户不存在时抛出"""
    pass

class BankAccountV2:
    def __init__(self, account_id, initial_balance=0):
        self.account_id = account_id
        self.balance = initial_balance
    
    def withdraw(self, amount):
        if amount > self.balance:
            raise InsufficientFundsError(self.balance, amount)
        self.balance -= amount
        return self.balance
    
    def deposit(self, amount):
        if amount <= 0:
            raise ValueError("Deposit amount must be positive")
        self.balance += amount
        return self.balance

class Bank:
    def __init__(self):
        self.accounts = {}
    
    def create_account(self, account_id, initial_balance=0):
        if account_id in self.accounts:
            raise InvalidAccountError(f"Account {account_id} already exists")
        self.accounts[account_id] = BankAccountV2(account_id, initial_balance)
        return self.accounts[account_id]
    
    def get_account(self, account_id):
        if account_id not in self.accounts:
            raise InvalidAccountError(f"Account {account_id} not found")
        return self.accounts[account_id]

# 使用示例
bank = Bank()

try:
    account = bank.create_account("ACC001", 1000)
    print(f"Created account with balance: {account.balance}")
    
    # 正常操作
    account.withdraw(500)
    print(f"After withdrawal: {account.balance}")
    
    # 触发异常
    account.withdraw(1000)
    
except InsufficientFundsError as e:
    print(f"Error: {e}")
    print(f"  Balance: {e.balance}, Attempted: {e.amount}")
    
except InvalidAccountError as e:
    print(f"Account error: {e}")

# 异常链
try:
    account = bank.get_account("ACC999")
except InvalidAccountError as e:
    try:
        account = bank.create_account("ACC999", 0)
    except InvalidAccountError as e2:
        raise RuntimeError("Failed to handle account") from e2

8. 总结

Python的面向对象编程提供了强大而灵活的工具来构建复杂的软件系统。从基础的类和对象,到高级的描述符和设计模式,掌握这些概念将显著提升代码质量和开发效率。

关键要点回顾:

  1. 封装:使用property和命名约定保护数据完整性
  2. 继承:合理使用继承,优先考虑组合
  3. 多态:利用duck typing和抽象基类
  4. 高级特性:描述符、魔术方法、dataclass等
  5. 设计模式:工厂、观察者等模式解决常见问题
  6. 最佳实践:组合优于继承,清晰的异常处理

通过本文的详细示例和解释,读者应该能够在实际项目中应用这些OOP概念,编写出更加优雅、可维护的Python代码。# 深入理解Python中的面向对象编程:从基础到高级实践

引言

面向对象编程(Object-Oriented Programming, OOP)是现代软件开发的核心范式之一。在Python中,OOP不仅提供了强大的代码组织能力,还通过封装、继承和多态等特性,帮助开发者构建可维护、可扩展的应用程序。本文将深入探讨Python中OOP的核心概念、高级特性以及实际应用,帮助读者从基础理解到高级实践。

1. 类与对象的基础

1.1 类的定义与实例化

在Python中,类是创建对象的蓝图。它定义了对象的属性和方法。以下是一个简单的类定义示例:

class Dog:
    # 类属性(所有实例共享)
    species = "Canis familiaris"
    
    def __init__(self, name, age):
        # 实例属性(每个实例独有)
        self.name = name
        self.age = age
    
    def bark(self):
        return f"{self.name} says woof!"
    
    def describe(self):
        return f"{self.name} is {self.age} years old"

# 创建实例
dog1 = Dog("Buddy", 3)
dog2 = Dog("Max", 5)

print(dog1.bark())  # Buddy says woof!
print(dog2.describe())  # Max is 5 years old
print(Dog.species)  # Canis familiaris

关键点:

  • __init__ 方法是构造函数,在创建实例时自动调用
  • self 参数指向实例本身
  • 类属性被所有实例共享,实例属性每个实例独有

1.2 实例方法、类方法与静态方法

Python提供了三种方法类型,各有不同的用途:

class Calculator:
    # 实例方法 - 操作实例数据
    def __init__(self):
        self.result = 0
    
    def add(self, x):
        self.result += x
        return self.result
    
    # 类方法 - 操作类数据(使用cls)
    @classmethod
    def get_description(cls):
        return f"This is a {cls.__name__} class"
    
    # 静态方法 - 独立于类和实例
    @staticmethod
    def multiply(x, y):
        return x * y

# 使用示例
calc = Calculator()
print(calc.add(5))  # 5
print(Calculator.get_description())  # This is a Calculator class
print(Calculator.multiply(3, 4))  # 12

方法类型对比:

方法类型 装饰器 第一个参数 访问权限
实例方法 self 可访问实例和类属性
类方法 @classmethod cls 只能访问类属性
静态方法 @staticmethod 不能访问实例或类属性

2. 封装与访问控制

2.1 Python的访问控制机制

Python通过命名约定实现访问控制,而不是严格的私有化:

class BankAccount:
    def __init__(self, account_holder, initial_balance):
        self.account_holder = account_holder  # 公共属性
        self._balance = initial_balance       # 受保护属性(约定)
        self.__pin = "1234"                   # 私有属性(名称修饰)
    
    # 公共方法
    def get_balance(self):
        return self._balance
    
    # 私有方法
    def __verify_pin(self, pin):
        return pin == self.__pin
    
    def withdraw(self, amount, pin):
        if self.__verify_pin(pin):
            if amount <= self._balance:
                self._balance -= amount
                return f"Withdrew {amount}. New balance: {self._balance}"
            return "Insufficient funds"
        return "Invalid PIN"

# 使用示例
account = BankAccount("Alice", 1000)
print(account.account_holder)  # Alice - 公共属性可访问
print(account._balance)        # 1000 - 约定保护,但技术上可访问
# print(account.__pin)         # AttributeError - 私有属性不可直接访问
# print(account.__verify_pin("1234"))  # AttributeError - 私有方法不可直接访问

print(account.withdraw(200, "1234"))  # Withdrew 200. New balance: 1000
print(account.withdraw(100, "9999"))  # Invalid PIN

Python名称修饰机制:

# Python解释器会将私有名称转换为:_类名__属性名
print(account._BankAccount__pin)  # '1234' - 可以这样访问,但不推荐

2.2 使用property装饰器实现真正的封装

class Temperature:
    def __init__(self, celsius):
        self._celsius = celsius
    
    @property
    def celsius(self):
        """获取摄氏温度"""
        return self._celsius
    
    @celsius.setter
    def celsius(self, value):
        """设置摄氏温度并验证"""
        if value < -273.15:
            raise ValueError("Temperature below absolute zero is impossible")
        self._celsius = value
    
    @property
    def fahrenheit(self):
        """计算华氏温度"""
        return (self._celsius * 9/5) + 32
    
    @fahrenheit.setter
    def fahrenheit(self, value):
        """通过华氏温度设置"""
        self.celsius = (value - 32) * 5/9  # 使用celsius setter进行验证

# 使用示例
temp = Temperature(25)
print(temp.celsius)      # 25
print(temp.fahrenheit)   # 77.0

temp.celsius = 30
print(temp.fahrenheit)   # 86.0

temp.fahrenheit = 100
print(temp.celsius)      # 37.77777777777778

# 验证失败
try:
    temp.celsius = -300
except ValueError as e:
    print(e)  # Temperature below absolute zero is impossible

3. 继承与多态

3.1 单继承与方法重写

class Animal:
    def __init__(self, name, species):
        self.name = name
        self.species = species
    
    def speak(self):
        raise NotImplementedError("Subclasses must implement speak method")
    
    def describe(self):
        return f"{self.name} is a {self.species}"

class Cat(Animal):
    def __init__(self, name, indoor=True):
        super().__init__(name, "Felis catus")
        self.indoor = indoor
    
    def speak(self):
        return "Meow"
    
    def describe(self):
        # 重写父类方法并扩展功能
        base_desc = super().describe()
        location = "indoor" if self.indoor else "outdoor"
        return f"{base_desc} ({location})"

class Dog(Animal):
    def __init__(self, name, breed):
        super().__init__(name, "Canis familiaris")
        self.breed = breed
    
    def speak(self):
        return "Woof!"
    
    def fetch(self, item):
        return f"{self.name} fetched {item}"

# 使用示例
animals = [
    Cat("Whiskers"),
    Dog("Buddy", "Golden Retriever"),
    Cat("Mittens", indoor=False)
]

for animal in animals:
    print(f"{animal.name}: {animal.speak()}")
    print(f"  {animal.describe()}")
    if isinstance(animal, Dog):
        print(f"  {animal.fetch('ball')}")

3.2 多继承与MRO(方法解析顺序)

Python支持多继承,使用C3线性化算法确定方法解析顺序:

class Flyer:
    def __init__(self, name):
        self.name = name
    
    def fly(self):
        return f"{self.name} is flying"

class Swimmer:
    def __init__(self, name):
        self.name = name
    
    def swim(self):
        return f"{self.name} is swimming"

class FlyingFish(Flyer, Swimmer):
    def __init__(self, name):
        # 注意:两个父类都有__init__,需要明确调用
        Flyer.__init__(self, name)
        # Swimmer.__init__(self, name)  # 如果调用会重复初始化name
    
    def describe(self):
        return f"{self.name} can both fly and swim"

# 使用示例
fish = FlyingFish("Swift")
print(fish.fly())    # Swift is flying
print(fish.swim())   # Swift is swimming
print(fish.describe())  # Swift can both fly and swim

# 查看MRO
print(FlyingFish.mro())
# [<class '__main__.FlyingFish'>, <class '__main__.Flyer'>, <class '__main__.Swimmer'>, <class 'object'>]

MRO冲突解决:

class A:
    def method(self):
        return "A"

class B(A):
    def method(self):
        return "B"

class C(A):
    def method(self):
        return "C"

class D(B, C):
    pass

# D的MRO: D -> B -> C -> A -> object
print(D.mro())  # [<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]

d = D()
print(d.method())  # "B" - 按照MRO顺序找到第一个method

4. 高级OOP特性

4.1 抽象基类(ABC)

from abc import ABC, abstractmethod
import numbers

class Shape(ABC):
    @abstractmethod
    def area(self):
        """计算面积"""
        pass
    
    @abstractmethod
    def perimeter(self):
        """计算周长"""
        pass
    
    def describe(self):
        return f"Area: {self.area():.2f}, Perimeter: {self.perimeter():.2f}"

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(5, 3), Circle(4)]

for shape in shapes:
    print(shape.describe())

# 尝试实例化未实现抽象方法的类会失败
try:
    class BadShape(Shape):
        pass
    bad = BadShape()
except TypeError as e:
    print(f"Error: {e}")  # Can't instantiate abstract class BadShape...

4.2 魔术方法(Dunder Methods)

class Vector2D:
    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"Vector2D({self.x}, {y})"
    
    # 算术运算
    def __add__(self, other):
        if isinstance(other, Vector2D):
            return Vector2D(self.x + other.x, self.y + other.y)
        return NotImplemented
    
    def __sub__(self, other):
        if isinstance(other, Vector2D):
            return Vector2D(self.x - other.x, self.y - other.y)
        return NotImplemented
    
    def __mul__(self, scalar):
        if isinstance(scalar, (int, float)):
            return Vector2D(self.x * scalar, self.y * scalar)
        return NotImplemented
    
    def __rmul__(self, scalar):
        return self.__mul__(scalar)
    
    # 比较运算
    def __eq__(self, other):
        if isinstance(other, Vector2D):
            return self.x == other.x and self.y == other.y
        return False
    
    def __lt__(self, other):
        if isinstance(other, Vector2D):
            return (self.x**2 + self.y**2) < (other.x**2 + other.y**2)
        return NotImplemented
    
    # 容器协议
    def __len__(self):
        return 2
    
    def __getitem__(self, key):
        if key == 0:
            return self.x
        elif key == 1:
            return self.y
        raise IndexError("Vector2D index out of range")
    
    def __iter__(self):
        return iter([self.x, self.y])
    
    # 可调用对象
    def __call__(self, other=None):
        if other is None:
            return self
        return self.__mul__(other)

# 使用示例
v1 = Vector2D(3, 4)
v2 = Vector2D(1, 2)

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

4.3 描述符(Descriptors)

描述符是实现了描述符协议的对象,用于控制属性访问:

class TypedProperty:
    """类型检查属性描述符"""
    def __init__(self, name, expected_type, default=None):
        self.name = "_" + name
        self.expected_type = expected_type
        self.default = default
    
    def __get__(self, instance, owner):
        if instance is None:
            return self
        return getattr(instance, self.name, self.default)
    
    def __set__(self, instance, value):
        if not isinstance(value, self.expected_type):
            raise TypeError(f"{self.name} must be of type {self.expected_type}")
        setattr(instance, self.name, value)
    
    def __delete__(self, instance):
        raise AttributeError(f"Cannot delete {self.name}")

class Product:
    # 使用描述符定义属性
    name = TypedProperty("name", str)
    price = TypedProperty("price", (int, float), default=0.0)
    quantity = TypedProperty("quantity", int, default=0)
    
    def __init__(self, name, price, quantity):
        self.name = name
        self.price = price
        self.quantity = quantity
    
    def total_cost(self):
        return self.price * self.quantity

# 使用示例
product = Product("Laptop", 999.99, 5)
print(product.name)      # Laptop
print(product.price)     # 999.99
print(product.total_cost())  # 4999.95

# 类型检查
try:
    product.price = "expensive"
except TypeError as e:
    print(e)  # _price must be of type (<class 'int'>, <class 'float'>)

try:
    bad_product = Product(123, 100, 5)  # name必须是str
except TypeError as e:
    print(e)  # _name must be of type <class 'str'>

# 删除属性会失败
try:
    del product.price
except AttributeError as e:
    print(e)  # Cannot delete _price

5. 设计模式在Python OOP中的应用

5.1 工厂模式

from abc import ABC, abstractmethod

class PaymentProcessor(ABC):
    @abstractmethod
    def process_payment(self, amount):
        pass

class CreditCardProcessor(PaymentProcessor):
    def __init__(self, card_number):
        self.card_number = card_number
    
    def process_payment(self, amount):
        return f"Processing ${amount} via Credit Card {self.card_number[-4:]}"

class PayPalProcessor(PaymentProcessor):
    def __init__(self, email):
        self.email = email
    
    def process_payment(self, amount):
        return f"Processing ${amount} via PayPal account {self.email}"

class CryptoProcessor(PaymentProcessor):
    def __init__(self, wallet_address):
        self.wallet_address = wallet_address
    
    def process_payment(self, amount):
        return f"Processing ${amount} via Crypto wallet {self.wallet_address[:8]}..."

class PaymentProcessorFactory:
    """工厂类创建支付处理器"""
    @staticmethod
    def create_processor(payment_type, **kwargs):
        processors = {
            'credit_card': CreditCardProcessor,
            'paypal': PayPalProcessor,
            'crypto': CryptoProcessor
        }
        
        if payment_type not in processors:
            raise ValueError(f"Unknown payment type: {payment_type}")
        
        return processors[payment_type](**kwargs)

# 使用示例
factory = PaymentProcessorFactory

# 创建不同的支付处理器
processor1 = factory.create_processor('credit_card', card_number="1234-5678-9012-3456")
processor2 = factory.create_processor('paypal', email="user@example.com")
processor3 = factory.create_processor('crypto', wallet_address="0x1234567890abcdef")

print(processor1.process_payment(100))  # Processing $100 via Credit Card 3456
print(processor2.process_payment(50))   # Processing $50 via PayPal account user@example.com
print(processor3.process_payment(200))  # Processing $200 via Crypto wallet 0x123456...

5.2 观察者模式

class Subject:
    """被观察的对象"""
    def __init__(self):
        self._observers = []
        self._state = None
    
    def attach(self, observer):
        if observer not in self._observers:
            self._observers.append(observer)
    
    def detach(self, observer):
        try:
            self._observers.remove(observer)
        except ValueError:
            pass
    
    def notify(self):
        for observer in self._observers:
            observer.update(self._state)
    
    def update_state(self, new_state):
        self._state = new_state
        self.notify()

class Observer(ABC):
    @abstractmethod
    def update(self, state):
        pass

class EmailNotifier(Observer):
    def update(self, state):
        print(f"Email: System state changed to {state}")

class SMSNotifier(Observer):
    def update(self, state):
        print(f"SMS: System state changed to {state}")

class LogNotifier(Observer):
    def update(self, state):
        print(f"Log: System state changed to {state}")

# 使用示例
subject = Subject()

email_notifier = EmailNotifier()
sms_notifier = SMSNotifier()
log_notifier = LogNotifier()

subject.attach(email_notifier)
subject.attach(sms_notifier)
subject.attach(log_notifier)

print("=== State changed to 'ERROR' ===")
subject.update_state("ERROR")

print("\n=== Detach SMS, state changed to 'OK' ===")
subject.detach(sms_notifier)
subject.update_state("OK")

6. Python OOP最佳实践

6.1 组合优于继承原则

# 不好的设计:过度使用继承
class Employee:
    def __init__(self, name, salary):
        self.name = name
        self.salary = salary

class Manager(Employee):
    def __init__(self, name, salary, department):
        super().__init__(name, salary)
        self.department = department
    
    def schedule_meeting(self):
        return f"Manager {self.name} schedules meeting"

class Developer(Employee):
    def __init__(self, name, salary, language):
        super().__init__(name, salary)
        self.language = language
    
    def write_code(self):
        return f"Developer {self.name} writes {self.language} code"

# 更好的设计:使用组合
class Role:
    def __init__(self, role_name):
        self.role_name = role_name
    
    def perform_duties(self):
        return f"Performing duties of {self.role_name}"

class ManagerRole(Role):
    def __init__(self, department):
        super().__init__("Manager")
        self.department = department
    
    def perform_duties(self):
        return f"Managing department {self.department}"

class DeveloperRole(Role):
    def __init__(self, language):
        super().__init__("Developer")
        self.language = language
    
    def perform_duties(self):
        return f"Writing {self.language} code"

class Employee:
    def __init__(self, name, salary, role):
        self.name = name
        self.salary = salary
        self.role = role
    
    def do_work(self):
        return f"{self.name} ({self.role.role_name}): {self.role.perform_duties()}"

# 使用组合的灵活性
manager = Employee("Alice", 80000, ManagerRole("Engineering"))
developer = Employee("Bob", 60000, DeveloperRole("Python"))

print(manager.do_work())    # Alice (Manager): Managing department Engineering
print(developer.do_work())  # Bob (Developer): Writing Python code

# 可以轻松改变角色
developer.role = ManagerRole("Sales")
print(developer.do_work())  # Bob (Manager): Managing department Sales

6.2 使用dataclass简化代码

from dataclasses import dataclass, field
from typing import List

@dataclass
class Student:
    name: str
    student_id: int
    grades: List[float] = field(default_factory=list)
    
    def add_grade(self, grade: float):
        self.grades.append(grade)
    
    def average(self):
        return sum(self.grades) / len(self.grades) if self.grades else 0
    
    def __str__(self):
        return f"Student {self.name} (ID: {self.student_id}) - Avg: {self.average():.2f}"

# 使用示例
student1 = Student("Charlie", 1001)
student1.add_grade(85)
student1.add_grade(92)
student1.add_grade(78)

student2 = Student("Diana", 1002, [95, 88, 91])

print(student1)  # Student Charlie (ID: 1001) - Avg: 85.00
print(student2)  # Student Diana (ID: 1002) - Avg: 91.33

# 自动生成的比较方法
print(student1 == Student("Charlie", 1001, [85, 92, 78]))  # True

7. 异常处理与OOP

7.1 自定义异常类

class InsufficientFundsError(Exception):
    """当账户余额不足时抛出"""
    def __init__(self, balance, amount):
        self.balance = balance
        self.amount = amount
        super().__init__(f"Insufficient funds: balance={balance}, attempted={amount}")

class InvalidAccountError(Exception):
    """当账户不存在时抛出"""
    pass

class BankAccountV2:
    def __init__(self, account_id, initial_balance=0):
        self.account_id = account_id
        self.balance = initial_balance
    
    def withdraw(self, amount):
        if amount > self.balance:
            raise InsufficientFundsError(self.balance, amount)
        self.balance -= amount
        return self.balance
    
    def deposit(self, amount):
        if amount <= 0:
            raise ValueError("Deposit amount must be positive")
        self.balance += amount
        return self.balance

class Bank:
    def __init__(self):
        self.accounts = {}
    
    def create_account(self, account_id, initial_balance=0):
        if account_id in self.accounts:
            raise InvalidAccountError(f"Account {account_id} already exists")
        self.accounts[account_id] = BankAccountV2(account_id, initial_balance)
        return self.accounts[account_id]
    
    def get_account(self, account_id):
        if account_id not in self.accounts:
            raise InvalidAccountError(f"Account {account_id} not found")
        return self.accounts[account_id]

# 使用示例
bank = Bank()

try:
    account = bank.create_account("ACC001", 1000)
    print(f"Created account with balance: {account.balance}")
    
    # 正常操作
    account.withdraw(500)
    print(f"After withdrawal: {account.balance}")
    
    # 触发异常
    account.withdraw(1000)
    
except InsufficientFundsError as e:
    print(f"Error: {e}")
    print(f"  Balance: {e.balance}, Attempted: {e.amount}")
    
except InvalidAccountError as e:
    print(f"Account error: {e}")

# 异常链
try:
    account = bank.get_account("ACC999")
except InvalidAccountError as e:
    try:
        account = bank.create_account("ACC999", 0)
    except InvalidAccountError as e2:
        raise RuntimeError("Failed to handle account") from e2

8. 总结

Python的面向对象编程提供了强大而灵活的工具来构建复杂的软件系统。从基础的类和对象,到高级的描述符和设计模式,掌握这些概念将显著提升代码质量和开发效率。

关键要点回顾:

  1. 封装:使用property和命名约定保护数据完整性
  2. 继承:合理使用继承,优先考虑组合
  3. 多态:利用duck typing和抽象基类
  4. 高级特性:描述符、魔术方法、dataclass等
  5. 设计模式:工厂、观察者等模式解决常见问题
  6. 最佳实践:组合优于继承,清晰的异常处理

通过本文的详细示例和解释,读者应该能够在实际项目中应用这些OOP概念,编写出更加优雅、可维护的Python代码。