1. 面向对象编程概述
面向对象编程(Object-Oriented Programming, OOP)是一种以对象为核心的编程范式。它将数据和操作数据的方法封装在一起,形成“对象”。与面向过程编程相比,OOP更贴近现实世界的建模,能有效提高代码的可重用性、可维护性和可扩展性。
Python是一门完全支持OOP的动态语言,其OOP实现简洁而强大。理解OOP是成为Python高级开发者的必经之路。
2. 类与对象:一切的基础
2.1 定义类与创建对象
类是对象的蓝图或模板,对象是类的实例。
# 定义一个简单的类 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!" 创建对象(实例化) my_dog = Dog("Buddy", 3) print(my_dog.name) # 输出: Buddy print(my_dog.bark()) # 输出: Buddy says: Woof! print(my_dog.species) # 输出: Canis familiaris2.2 self关键字与实例方法
self代表类的实例本身,在实例方法中必须作为第一个参数。通过self可以访问实例的属性和其他方法。
class Calculator: def __init__(self): self.result = 0 def add(self, value): self.result += value return self def multiply(self, value): self.result *= value return self def get_result(self): return self.result calc = Calculator() final = calc.add(5).multiply(3).add(10).get_result() print(final) # 输出: 253. 面向对象三大特性
3.1 封装(Encapsulation)
封装是将数据(属性)和操作数据的方法(行为)捆绑在一起,并对外隐藏内部实现细节。在Python中,主要通过命名约定来实现访问控制。
class BankAccount: def __init__(self, owner, balance=0): self.owner = owner self._balance = balance # 受保护属性(单下划线约定) self.__account_id = id(self) # 私有属性(双下划线,名称修饰) def deposit(self, amount): if amount > 0: self._balance += amount return True return False def withdraw(self, amount): if 0 < amount <= self._balance: self._balance -= amount return True return False 公共接口(getter) def get_balance(self): return self._balance account = BankAccount("Alice", 1000) print(account.get_balance()) # 输出: 1000 print(account.__account_id) # 报错:AttributeError 但可以通过名称修饰访问(不推荐): _BankAccount__account_id3.2 继承(Inheritance)
继承允许一个类(子类)获取另一个类(父类)的属性和方法,实现代码复用和层次化设计。
# 父类(基类) class Animal: def __init__(self, name): self.name = name def speak(self): raise NotImplementedError("子类必须实现此方法") 子类(派生类) class Dog(Animal): def speak(self): return f"{self.name} says Woof!" class Cat(Animal): def speak(self): return f"{self.name} says Meow!" 使用 animals = [Dog("Buddy"), Cat("Whiskers")] for animal in animals: print(animal.speak()) 输出: Buddy says Woof! Whiskers says Meow!3.2.1 方法重写(Override)与super()
class Vehicle: def __init__(self, brand, model): self.brand = brand self.model = model def info(self): return f"{self.brand} {self.model}" class ElectricCar(Vehicle): def init(self, brand, model, battery_capacity): # 调用父类的__init__ super().init(brand, model) self.battery_capacity = battery_capacity # 重写父类方法 def info(self): base_info = super().info() return f"{base_info} (Electric, {self.battery_capacity}kWh)" tesla = ElectricCar("Tesla", "Model 3", 75) print(tesla.info()) # 输出: Tesla Model 3 (Electric, 75kWh)3.2.2 多重继承与MRO(方法解析顺序)
class A: def show(self): print("A") class B(A): def show(self): print("B") super().show() class C(A): def show(self): print("C") super().show() class D(B, C): def show(self): print("D") super().show() d = D() d.show() 输出顺序(遵循C3线性化算法): D B C A print(D.mro) # 查看方法解析顺序 输出: (<class 'main.D'>, <class 'main.B'>, <class 'main.C'>, <class 'main.A'>, <class 'object'>)3.3 多态(Polymorphism)
多态指同一操作作用于不同的对象,可以有不同的解释和执行结果。在Python中,多态主要通过“鸭子类型”实现。
class PDFExporter: def export(self, data): return f"导出PDF: {data}" class CSVExporter: def export(self, data): return f"导出CSV: {data}" class JSONExporter: def export(self, data): return f"导出JSON: {data}" 多态的使用 exporters = [PDFExporter(), CSVExporter(), JSONExporter()] data = "销售报告" for exporter in exporters: print(exporter.export(data)) 输出: 导出PDF: 销售报告 导出CSV: 销售报告 导出JSON: 销售报告4. 类与实例的高级特性
4.1 类方法与静态方法
class MyClass: class_attribute = "类属性" def __init__(self, value): self.instance_attribute = value 实例方法:接收self,操作实例 def instance_method(self): return f"实例属性: {self.instance_attribute}" 类方法:接收cls,操作类本身,用@classmethod装饰 @classmethod def class_method(cls): return f"类属性: {cls.class_attribute}" 静态方法:不接收self或cls,只是逻辑上属于类,用@staticmethod装饰 @staticmethod def static_method(): return "这是一个静态方法" obj = MyClass("实例值") print(obj.instance_method()) # 实例属性: 实例值 print(MyClass.class_method()) # 类属性: 类属性 print(MyClass.static_method()) # 这是一个静态方法4.2 属性装饰器@property
将方法“伪装”成属性,实现更优雅的getter、setter、deleter。
class Circle: def __init__(self, radius): self._radius = radius @property def radius(self): """获取半径""" return self._radius @radius.setter def radius(self, value): """设置半径,需为正数""" if value <= 0: raise ValueError("半径必须为正数") self._radius = value @property def area(self): """计算面积(只读属性)""" return 3.14159 * self._radius ** 2 @property def diameter(self): """直径(只读属性)""" return 2 * self._radius circle = Circle(5) print(circle.radius) # 5 print(circle.area) # 78.53975 circle.radius = 10 print(circle.area) # 314.159 circle.area = 100 # 报错:AttributeError: can't set attribute5. 魔术方法(特殊方法)
以双下划线开头和结尾的方法,用于实现类的特殊行为。
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}, {self.y})" 算术运算 def add(self, other): return Vector(self.x + other.x, self.y + other.y) def sub(self, other): return Vector(self.x - other.x, self.y - other.y) def mul(self, scalar): return Vector(self.x * scalar, self.y * scalar) 比较运算 def eq(self, other): return self.x == other.x and self.y == other.y def lt(self, other): # 比较模长 return (self.x2 + self.y2) < (other.x2 + other.y2) 容器模拟 def len(self): return 2 # 二维向量 def getitem(self, index): if index == 0: return self.x elif index == 1: return self.y else: raise IndexError("Vector索引只能是0或1") v1 = Vector(2, 3) v2 = Vector(4, 5) print(v1 + v2) # Vector(6, 8) print(v1 * 3) # Vector(6, 9) print(v1 == Vector(2, 3)) # True print(v1[0]) # 26. 抽象基类(ABC)与接口设计
from abc import ABC, abstractmethod 定义抽象基类 class Shape(ABC): @abstractmethod def area(self): pass @abstractmethod def perimeter(self): pass 抽象基类也可以有具体方法 def describe(self): return f"这是一个形状,面积={self.area()},周长={self.perimeter()}" 具体实现 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(4, 5), Circle(3)] for shape in shapes: print(shape.describe()) 输出: 这是一个形状,面积=20,周长=18 这是一个形状,面积=28.27431,周长=18.849547. 混入类(Mixin)与组合
# 混入类:提供特定功能 class JSONSerializableMixin: def to_json(self): import json return json.dumps(self.__dict__) class XMLSerializableMixin: def to_xml(self): # 简化实现 attrs = " ".join([f'{k}="{v}"' for k, v in self.dict.items()]) return f"<object {attrs}/>" 日志混入 class LoggableMixin: def log(self, message): print(f"[LOG] {self.class.name}: {message}") 使用混入 class Product(JSONSerializableMixin, LoggableMixin): def init(self, name, price): self.name = name self.price = price def apply_discount(self, percent): self.price *= (1 - percent/100) self.log(f"应用{percent}%折扣,新价格: {self.price}") product = Product("Laptop", 1000) print(product.to_json()) # {"name": "Laptop", "price": 1000} product.apply_discount(10) # [LOG] Product: 应用10%折扣,新价格: 900.08. 描述符(Descriptor)
描述符是实现属性访问控制的底层机制,@property就是基于描述符实现的。
# 自定义描述符:验证整数范围 class RangeValidator: def __init__(self, min_value, max_value): self.min_value = min_value self.max_value = max_value self.data = {} def __get__(self, obj, objtype=None): if obj is None: return self return self.data.get(id(obj)) def set(self, obj, value): if not (self.min_value <= value <= self.max_value): raise ValueError(f"值必须在{self.min_value}到{self.max_value}之间") self.data[id(obj)] = value def delete(self, obj): del self.data[id(obj)] class Person: age = RangeValidator(0, 150) score = RangeValidator(0, 100) def init(self, name, age, score): self.name = name self.age = age # 触发描述符的__set__ self.score = score p = Person("Alice", 25, 85) print(p.age) # 25 p.age = 200 # ValueError: 值必须在0到150之间 p.score = -10 # ValueError: 值必须在0到100之间9. 元类(Metaclass)
元类是“类的类”,用于控制类的创建行为。
# 自定义元类:自动注册所有子类 class PluginRegistry(type): plugins = [] def __new__(cls, name, bases, attrs): new_class = super().__new__(cls, name, bases, attrs) if name != "BasePlugin": # 不注册基类 cls.plugins.append(new_class) return new_class 使用元类 class BasePlugin(metaclass=PluginRegistry): pass class EmailPlugin(BasePlugin): def execute(self): print("发送邮件") class SMSPlugin(BasePlugin): def execute(self): print("发送短信") print(f"已注册插件: {[p.name for p in PluginRegistry.plugins]}") 输出: 已注册插件: ['EmailPlugin', 'SMSPlugin']10. 综合实战:简易电商系统设计
from abc import ABC, abstractmethod from datetime import datetime from typing import List 抽象基类 class Product(ABC): def init(self, name: str, price: float): self.name = name self._price = price @property def price(self): return self._price @abstractmethod def get_description(self): pass 具体产品类 class Book(Product): def init(self, name: str, price: float, author: str, pages: int): super().init(name, price) self.author = author self.pages = pages def get_description(self): return f"《{self.name}》- {self.author}著,共{self.pages}页" class Electronics(Product): def __in