2.1 类与对象
概念:什么是面向对象?
面向对象编程(OOP)是一种编程范式,将数据和操作数据的方法组织为"对象"。类是对象的蓝图/模板,通过实例化类来创建对象。OOP 的核心思想是将现实世界的事物抽象为程序中的对象,每个对象有自己的属性(数据)和方法(行为)。
面向对象基础
python
# 类:模板/蓝图,用于创建对象
# 对象:类的实例
# 定义类
class Dog:
"""狗类"""
# 类属性(所有实例共享)
species = "犬科"
# 实例方法(第一个参数是 self)
def bark(self):
return "汪汪汪!"
def __init__(self, name, age):
"""初始化方法,创建对象时自动调用"""
self.name = name # 实例属性
self.age = age
def __str__(self):
"""返回字符串表示,用于 print"""
return f"{self.name},{self.age}岁"
def __repr__(self):
"""返回官方字符串表示,用于调试"""
return f"Dog(name={self.name!r}, age={self.age!r})"
# 创建对象(实例化)
dog1 = Dog("旺财", 3)
dog2 = Dog("小白", 5)
# 访问属性和方法
print(dog1.name) # 旺财
print(dog1.bark()) # 汪汪汪!
print(dog1.species) # 犬科(类属性)
概念:self 是什么?
self 是对当前对象实例的引用,类似于其他语言中的 this指针。在实例方法中,self 用来访问对象的属性和其他方法。Python 会自动将 self 传递给实例方法的第一个参数。
python
class Person:
def __init__(self, name):
self.name = name # self 指向当前对象
def greet(self):
return f"你好,我是{self.name}" # self 访问对象的属性和方法
概念:类属性 vs 实例属性
- 类属性:定义在类中,所有对象共享,通常用于定义常量或类级别的数据
- 实例属性 :定义在 \_init\\ 中,每个对象独立拥有
python
class Dog:
species = "犬科" # 类属性:所有对象共享
def __init__(self, name):
self.name = name # 实例属性:每个对象独立
dog1 = Dog("旺财")
dog2 = Dog("小白")
dog1.species = "猫科" # 只影响 dog1,创建了新的实例属性
print(dog2.species) # 犬科(不变)
print(Dog.species) # 犬科(类属性不变)
概念:魔法方法(特殊方法)
魔法方法是以双下划线开头和结尾的特殊方法,也叫"Dunder Methods"。它们在特定操作发生时自动调用,例如 \\\\init\\ \\ 在创建对象时调用,\\\\str\\\\ 在 print 对象时调用。
python
class Person:
def __new__(cls, *args, **kwargs):
"""创建对象前调用,返回对象"""
print("创建对象中...")
return super().__new__(cls)
def __init__(self, name):
print("初始化对象...")
self.name = name
def __del__(self):
"""对象被删除时调用"""
print(f"{self.name} 被删除了")
def __call__(self):
"""使对象可调用,像函数一样"""
return f"{self.name} 被调用了"
2.2 继承与多态
概念:什么是继承?
继承是面向对象的核心特性之一,允许我们定义一个类(子类)来继承另一个类(父类)的属性和方法。子类可以重用父类的代码,还可以添加自己的新属性和方法,或重写父类的方法。
单继承
python
# 基类(父类)
class Animal:
def __init__(self, name):
self.name = name
def speak(self):
return "..."
# 派生类(子类)
class Dog(Animal):
def __init__(self, name, breed):
super().__init__(name) # 调用父类 __init__
self.breed = breed # 新增属性
def speak(self): # 重写父类方法
return f"{self.name} 汪汪汪!"
dog = Dog("旺财", "哈士奇")
print(dog.name) # 旺财(继承自父类)
print(dog.speak()) # 旺财 汪汪汪!(重写后的方法)
概念:多继承
Python 支持一个类继承多个父类,叫多继承。但多继承会增加复杂度,可能出现方法解析顺序(MRO)问题,使用时需要谨慎。
python
class Flyable:
def fly(self):
return "我可以飞!"
class Swimmable:
def swim(self):
return "我可以游泳!"
# 多继承
class Duck(Animal, Flyable, Swimmable):
pass
duck = Duck("唐老鸭")
print(duck.fly()) # 我可以飞!
print(duck.swim()) # 我可以游泳!
概念:MRO(方法解析顺序)
MRO 是 Python 用于决定在多继承情况下,应该从哪个父类开始查找方法/属性的顺序。可以通过 类名.mro() 或 类名.\\mro\\ 查看。
python
class A:
def greet(self):
return "A"
class B(A):
pass
class C(A):
def greet(self):
return "C"
class D(B, C):
pass
print(D.mro()) # [<class 'D'>, <class 'B'>, <class 'C'>, <class 'A'>, <class 'object'>]
print(D().greet()) # C(按 MRO 顺序查找)
概念:super() 函数
super() 用于在子类中调用父类的方法,是实现类继承层级协作的关键。最常见的是在子类的 \\\\init\\ \\ 中调用 super().\\__init\\\\()。
python
class Parent:
def __init__(self, name):
self.name = name
class Child(Parent):
def __init__(self, name, age):
super().__init__(name) # 调用父类方法
self.age = age
# super() 也可以在普通方法中使用
class Child2(Parent):
def greet(self):
return f"Hello, {super().greet()}"
概念:什么是多态?
多态是指同一种方法调用在不同对象上有不同行为的特性。简单说就是"同一个接口,不同实现"。Python 天生支持多态,因为它是动态类型语言,不需要显式声明接口。
python
# 同一个方法,不同对象有不同行为
class Cat(Animal):
def speak(self):
return "喵喵喵!"
class Dog(Animal):
def speak(self):
return "汪汪汪!"
# 统一接口
def make_noise(animal):
print(animal.speak())
animals = [Dog("旺财"), Cat("咪咪"), Dog("小白")]
for animal in animals:
make_noise(animal)
# 输出:
# 汪汪汪!
# 喵喵喵!
# 汪汪汪!
2.3 封装
概念:什么是封装?
封装是面向对象的三大特性之一(另两个是继承和多态)。封装的目的是隐藏对象的内部细节,只暴露必要的接口。Python 通过命名约定来实现封装:单下划线 \_ 表示"受保护",双下划线 \\__ 表示"私有"。
访问控制
python
class Person:
def __init__(self, name, age):
self.name = name # 公有属性(可访问)
self._age = age # 保护属性(约定不直接访问)
self.__phone = "123456" # 私有属性(名字重整)
def get_phone(self): # 访问私有属性
return self.__phone
def _protected_method(self): # 保护方法
return "这是一个受保护的方法"
def __private_method(self): # 私有方法
return "这是一个私有方法"
person = Person("Alice", 25)
print(person.name) # Alice(正常访问)
print(person._age) # 25(可以访问,但不推荐)
print(person.get_phone()) # 123456(通过方法访问)
# 名字重整:_Person__phone
print(person._Person__phone) # 123456(可以访问,但不推荐)
概念:property 装饰器
property 装饰器允许我们将方法当作属性来访问,实现"Getter"。配合 .setter 和 .deleter,可以实现完整的属性控制,实现数据封装和验证。
python
class Person:
def __init__(self, name):
self._name = name
@property
def name(self):
"""获取 name"""
return self._name
@name.setter
def name(self, value):
"""设置 name"""
if not value:
raise ValueError("名字不能为空")
self._name = value
@name.deleter
def name(self):
"""删除 name"""
del self._name
person = Person("Alice")
print(person.name) # Alice(调用 getter)
person.name = "Bob" # 调用 setter
print(person.name) # Bob
del person.name # 调用 deleter
私有属性访问器模式
python
class BankAccount:
def __init__(self, balance):
self.__balance = balance # 私有属性
def get_balance(self): # getter
return self.__balance
def set_balance(self, value): # setter
if value < 0:
raise ValueError("余额不能为负")
self.__balance = value
def deposit(self, amount): # 业务方法
if amount <= 0:
raise ValueError("存款金额必须为正")
self.__balance += amount
def withdraw(self, amount):
if amount > self.__balance:
raise ValueError("余额不足")
self.__balance -= amount
2.4 类方法与静态方法
概念:三种方法的区别
- 实例方法:第一个参数是 self,只能通过实例调用,可以访问和修改实例属性
- 类方法:第一个参数是 cls(类本身),可以通过类或实例调用,可以访问类属性但不能访问实例属性
- 静态方法:没有任何默认参数,跟普通函数一样,可以通过类或实例调用,但不能访问类或实例属性
实例方法、类方法、静态方法对比
python
class MyClass:
class_attr = "类属性"
def instance_method(self):
"""实例方法:第一个参数是 self"""
return "实例方法", self
@classmethod
def class_method(cls):
"""类方法:第一个参数是类本身"""
return "类方法", cls, cls.class_attr
@staticmethod
def static_method():
"""静态方法:没有默认参数"""
return "静态方法"
# 调用
obj = MyClass()
obj.instance_method() # 需要实例
MyClass.instance_method(obj) # 也可以用实例调用
MyClass.class_method() # 可以用类直接调用
obj.class_method() # 也可以用实例调用
MyClass.static_method() # 可以用类直接调用
obj.static_method() # 也可以用实例调用
类方法的应用场景
python
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
@classmethod
def from_dict(cls, data):
"""从字典创建对象"""
return cls(data["name"], data["age"])
@classmethod
def from_string(cls, string):
"""从字符串创建对象"""
name, age = string.split(",")
return cls(name.strip(), int(age))
# 使用类方法创建对象
data = {"name": "Alice", "age": 25}
person1 = Person.from_dict(data)
person2 = Person.from_string("Bob, 30")
静态方法的应用场景
python
class MathUtils:
@staticmethod
def add(a, b):
"""工具方法,与类相关但不依赖类或实例"""
return a + b
@staticmethod
def is_valid_age(age):
"""判断年龄是否合法"""
return 0 <= age <= 150
print(MathUtils.add(1, 2)) # 3
print(MathUtils.is_valid_age(25)) # True
2.5 特殊方法(魔术方法)
概念:什么是魔术方法?
魔术方法(Magic Methods)或特殊方法,是以双下划线 __ 开头和结尾的方法。它们不是普通方法,而是在特定操作时由 Python 自动调用的"钩子"。通过重写这些方法,可以让自定义对象支持 Python 的内置操作(如 +、==、len() 等)。
常用特殊方法一览
python
class MyClass:
def __init__(self, value):
self.value = value
# 字符串表示
def __str__(self):
return f"MyClass({self.value})"
def __repr__(self):
return f"MyClass(value={self.value!r})"
# 比较运算符
def __eq__(self, other):
return self.value == other.value
def __lt__(self, other):
return self.value < other.value
def __le__(self, other):
return self.value <= other.value
def __gt__(self, other):
return self.value > other.value
def __ge__(self, other):
return self.value >= other.value
# 算术运算符
def __add__(self, other):
return MyClass(self.value + other.value)
def __sub__(self, other):
return MyClass(self.value - other.value)
def __mul__(self, other):
return MyClass(self.value * other.value)
def __truediv__(self, other):
return MyClass(self.value / other.value)
# 一元运算符
def __neg__(self):
return MyClass(-self.value)
def __abs__(self):
return MyClass(abs(self.value))
# 长度和迭代
def __len__(self):
return len(self.value)
def __iter__(self):
return iter(self.value)
def __contains__(self, item):
return item in self.value
# 调用
def __call__(self):
return f"调用了 MyClass({self.value})"
# 索引访问
def __getitem__(self, index):
return self.value[index]
def __setitem__(self, index, value):
self.value[index] = value
# 上下文管理
def __enter__(self):
return self
def __exit__(self, exc_type, exc_val, exc_tb):
pass
完整示例:向量类
python
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):
return self.x == other.x and self.y == other.y
def __add__(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 __abs__(self):
return (self.x ** 2 + self.y ** 2) ** 0.5
v1 = Vector(3, 4)
v2 = Vector(1, 2)
print(v1) # Vector(3, 4)
print(v1 + v2) # Vector(4, 6)
print(v1 * 2) # Vector(6, 8)
print(abs(v1)) # 5.0
2.6 装饰器
概念:什么是装饰器?
装饰器是 Python 的高级特性,它本质上是一个函数,用于在不修改原函数的情况下,给函数添加新的功能。可以把装饰器理解为"包装"函数的高阶函数。装饰器广泛用于日志记录、性能测试、权限验证、缓存等场景。
函数装饰器
python
# 装饰器是一个函数,接收函数作为参数,返回新函数
def my_decorator(func):
def wrapper(*args, **kwargs):
print("调用前")
result = func(*args, **kwargs)
print("调用后")
return result
return wrapper
@my_decorator
def say_hello(name):
print(f"Hello, {name}!")
# 等价于
# say_hello = my_decorator(say_hello)
say_hello("Alice")
# 输出:
# 调用前
# Hello, Alice!
# 调用后
概念:装饰器带参数
装饰器工厂(Decorator Factory)是返回装饰器的函数。通过装饰器工厂可以给装饰器传递参数,实现更灵活的功能配置。
python
def repeat(times):
"""装饰器工厂:返回装饰器"""
def decorator(func):
def wrapper(*args, **kwargs):
for _ in range(times):
result = func(*args, **kwargs)
return result
return wrapper
return decorator
@repeat(3)
def greet(name):
print(f"Hello, {name}!")
greet("Alice")
# 输出: Hello, Alice! 三次
类装饰器
python
class MyDecorator:
def __init__(self, func):
self.func = func
def __call__(self, *args, **kwargs):
print("调用前")
return self.func(*args, **kwargs)
@MyDecorator
def say_hello(name):
print(f"Hello, {name}!")
概念:functools.wraps 的作用
装饰器在包装原函数时,会丢失原函数的元信息(如 \\__name\\、\\doc\\ 等)。使用 @functools.wraps(func) 可以保留这些元信息,对调试和文档生成很重要。
python
import functools
def my_decorator(func):
@functools.wraps(func) # 保留原函数的信息
def wrapper(*args, **kwargs):
print("调用前")
return func(*args, **kwargs)
return wrapper
@my_decorator
def say_hello(name):
"""问候函数"""
print(f"Hello, {name}!")
print(say_hello.__name__) # say_hello(而不是 wrapper)
print(say_hello.__doc__) # 问候函数
常见装饰器
python
# property 装饰器(已在 2.3 讲过)
# classmethod 装饰器(已在 2.4 讲过)
# staticmethod 装饰器(已在 2.4 讲过)
# 缓存装饰器
import functools
def cache(func):
cache_dict = {}
@functools.wraps(func)
def wrapper(*args):
if args not in cache_dict:
cache_dict[args] = func(*args)
return cache_dict[args]
return wrapper
@cache
def fibonacci(n):
if n < 2:
return n
return fibonacci(n-1) + fibonacci(n-2)
2.7 生成器与迭代器
概念:什么是迭代器协议?
迭代器是实现了 \\__iter\\\\ 和 \\__next\\\\ 两个方法的对象。迭代器协议是 Python 中用于遍历集合的标准方式,通过 next() 函数获取下一个元素,当没有更多元素时抛出 StopIteration 异常。
迭代器协议
python
# 迭代器:实现了 __iter__ 和 __next__ 的对象
class Counter:
def __init__(self, limit):
self.limit = limit
self.current = 0
def __iter__(self):
return self
def __next__(self):
if self.current < self.limit:
result = self.current
self.current += 1
return result
raise StopIteration # 迭代结束
counter = Counter(5)
for i in counter:
print(i) # 0, 1, 2, 3, 4
概念:什么是生成器?
生成器是一种特殊的迭代器,使用 yield 关键字来返回值。与普通函数返回后结束不同,生成器函数在执行过程中可以暂停和恢复,yield 会保存函数的状态。生成器非常适合处理大数据流,可以节省内存。
生成器函数
python
# 使用 yield 的函数就是生成器函数
def countdown(n):
"""倒数生成器"""
while n > 0:
yield n
n -= 1
for num in countdown(5):
print(num) # 5, 4, 3, 2, 1
# 生成器是迭代器的一种,更简单
gen = countdown(3)
print(next(gen)) # 5
print(next(gen)) # 4
print(next(gen)) # 3
print(next(gen)) # StopIteration
生成器表达式
python
# 类似列表推导式,但用圆括号,返回生成器
squares = (x**2 for x in range(5))
print(next(squares)) # 0
print(next(squares)) # 1
# 节省内存,适合大数据
million_squares = (x**2 for x in range(1000000))
# 不占用额外内存,直到迭代时才计算
概念:yield from
yield from 是 Python 3.3 引入的新语法,用于简化在生成器中委托给另一个生成器。它允许我们直接"透传"yield 操作给子生成器,而不需要使用循环。
python
def flatten(nested):
"""扁平化嵌套列表"""
for item in nested:
if isinstance(item, list):
yield from flatten(item)
else:
yield item
result = list(flatten([1, [2, 3], [4, [5, 6]]]))
print(result) # [1, 2, 3, 4, 5, 6]
迭代工具
python
from itertools import count, cycle, repeat, chain, zip_longest, islice
# count: 无限计数
for i in zip(range(5), count(10)):
print(i) # (0, 10), (1, 11), (2, 12), (3, 13), (4, 14)
### 文章摘要生成方法
确定文章核心主题和关键论点,确保摘要涵盖主要观点。避免冗余细节,聚焦于文章的核心价值。
提取文章中的关键数据、案例或结论,用简洁语言概括。保持逻辑连贯性,使读者能快速理解文章主旨。
检查摘要是否独立完整,无需依赖原文即可传达核心信息。确保语言精炼,控制在指定字数内。
对于技术或学术文章,突出研究方法、发现或创新点。非专业读者也能通过摘要把握文章要点。
将摘要分为背景、方法、结果、结论四个部分,每部分用1-2句话概括。这种结构适用于大多数学术性文章。
# cycle: 无限循环
for i, c in zip(range(8), cycle("ABC")):
print(f"{i}: {c}")
# repeat: 重复元素
for item in repeat("A", 3):
print(item) # A, A, A
# chain: 连接多个迭代器
for item in chain([1, 2], ['a', 'b']):
print(item) # 1, 2, a, b
# islice: 切片迭代器
import itertools
for item in itertools.islice(range(10), 2, 8, 2):
print(item) # 2, 4, 6
2.8 上下文管理器
概念:什么是上下文管理器?
上下文管理器是一种支持 with 语句的对象,它在进入代码块前执行"进入"操作,在退出代码块后执行"退出"操作。最常见的用途是资源管理:确保文件、网络连接、锁等资源在使用后正确关闭或释放,即使发生异常也不会遗漏。
with 语句
python
# 上下文管理器:实现了 __enter__ 和 __exit__ 的对象
# 用于资源管理,自动获取和释放资源
with open("test.txt", "w") as f:
f.write("Hello")
# 文件自动关闭
# 等价于
f = open("test.txt", "w")
try:
f.write("Hello")
finally:
f.close()
类实现上下文管理器
python
class FileManager:
def __init__(self, filename, mode):
self.filename = filename
self.mode = mode
self.file = None
def __enter__(self):
self.file = open(self.filename, self.mode)
return self.file
def __exit__(self, exc_type, exc_val, exc_tb):
if self.file:
self.file.close()
# return True 可以抑制异常(但不推荐)
with FileManager("test.txt", "w") as f:
f.write("Hello")
contextlib 模块
python
import contextlib
# 1. contextmanager 装饰器
@contextlib.contextmanager
def managed_resource():
print("获取资源")
yield "资源"
print("释放资源")
with managed_resource() as resource:
print(f"使用 {resource}")
# 输出:
# 获取资源
# 使用 资源
# 释放资源
# 2. closing:自动调用 close()
@contextlib.closing
def open_file():
f = open("test.txt", "w")
return f
with open_file() as f:
f.write("Hello")
# 3. suppress:忽略指定异常
with contextlib.suppress(FileNotFoundError):
os.remove("nonexistent.txt")
# 4. redirect_stdout:重定向标准输出
import io
with contextlib.redirect_stdout(io.StringIO()) as f:
print("Hello")
output = f.getvalue()
2.9 类型注解
概念:什么是类型注解?
类型注解是 Python 3.5+ 引入的特性,允许在代码中为变量、函数参数和返回值添加类型提示。这是可选的,不会影响代码运行,但可以帮助 IDE 进行代码补全、类型检查(如 mypy),并使代码更易读。
基础类型注解
python
# 变量注解
name: str = "Alice"
age: int = 25
height: float = 1.68
is_student: bool = True
# 函数注解
def greet(name: str) -> str:
return f"Hello, {name}"
def add(a: int, b: int) -> int:
return a + b
概念:复杂类型注解
typing 模块提供了用于复杂类型注解的工具,包括 List、Dict、Tuple、Optional、Union、Callable 等,适用于集合类型、可选值、联合类型和函数类型等场景。
复杂类型注解
python
from typing import List, Dict, Tuple, Set, Optional, Union, Callable
# 列表
numbers: List[int] = [1, 2, 3]
# 字典
person: Dict[str, Union[str, int]] = {"name": "Alice", "age": 25}
# 元组
point: Tuple[int, int] = (3, 4)
# 集合
unique_numbers: Set[int] = {1, 2, 3}
# 可选类型
name: Optional[str] = None # 等价于 Union[str, None]
# 联合类型
result: Union[int, str] = 42
# 可调用对象
def callback(func: Callable[[int, int], int]):
return func(1, 2)
# 匿名函数类型
operation: Callable[[int, int], int] = lambda x, y: x + y
typing 模块常用类型
python
from typing import Any, NoReturn, TypeVar, Generic, Iterator
# Any:任意类型
def func(x: Any) -> Any:
return x
# NoReturn:无返回值
def error() -> NoReturn:
raise ValueError("错误")
# TypeVar:类型变量
T = TypeVar('T')
def first(lst: List[T]) -> Optional[T]:
return lst[0] if lst else None
# 泛型
from typing import TypeVar
T = TypeVar('T')
class Stack(Generic[T]):
def __init__(self):
self._items: List[T] = []
def push(self, item: T):
self._items.append(item)
def pop(self) -> T:
return self._items.pop()
运行时类型检查
python
# 类型注解不影响运行时,使用 typing.get_type_hints() 获取
def greet(name: str) -> str:
return f"Hello, {name}"
import typing
hints = typing.get_type_hints(greet)
print(hints) # {'name': <class 'str'>, 'return': <class 'str'>}
# 第三方库如 pydantic 可以进行运行时验证
2.10 描述符协议
概念:什么是描述符?
描述符是 Python 最强大也最隐秘的特性之一。它是一种类属性,通过实现 \\__get\\\\ 、\\__set\\\\ 、\\__delete\\\\ 方法来控制对另一个类属性的访问。property 装饰器就是基于描述符协议实现的。
描述符是什么
python
# 描述符:实现了 __get__ 和 __set__ 的类属性
# 用于控制属性的访问、修改和删除
class Score:
def __init__(self):
self._score = 0
def __get__(self, instance, owner):
print(f"获取 score: {self._score}")
return self._score
def __set__(self, instance, value):
if value < 0 or value > 100:
raise ValueError("分数必须在 0-100 之间")
print(f"设置 score: {value}")
self._score = value
def __delete__(self, instance):
print("删除 score")
del self._score
class Student:
score = Score() # 类属性是描述符
student = Student()
student.score = 95 # 设置 score: 95
print(student.score) # 获取 score: 95 / 95
del student.score # 删除 score
property vs 描述符
python
# property 是描述符的简化形式
class Person:
@property
def name(self):
return self._name
@name.setter
def name(self, value):
self._name = value
# 等价的描述符实现
class NameDescriptor:
def __get__(self, instance, owner):
return instance._name
def __set__(self, instance, value):
instance._name = value
class Person2:
name = NameDescriptor()
2.11 元类基础
概念:什么是元类?
元类是"类的类"。普通类定义了如何创建对象,而元类定义了如何创建类。默认情况下,所有类都是用 type 作为元类创建。通过自定义元类,我们可以在类创建时修改类的行为,比如自动注册类、强制子类实现某些方法等。
type 创建类
python
# type 三个参数:类名、基类元组、属性字典
MyClass = type("MyClass", (), {"value": 42})
obj = MyClass()
print(obj.value) # 42
自定义元类
python
# 元类:类的类,用于控制类的创建
class MyMeta(type):
def __new__(mcs, name, bases, attrs):
print(f"创建类: {name}")
# 可以修改类的属性
attrs["class_name"] = name
return super().__new__(mcs, name, bases, attrs)
class MyClass(metaclass=MyMeta):
pass
# 输出: 创建类: MyClass
print(MyClass.class_name) # MyClass
元类应用场景
python
# 1. 注册类
class RegistryMeta(type):
registry = {}
def __new__(mcs, name, bases, attrs):
cls = super().__new__(mcs, name, bases, attrs)
if name != "Base":
RegistryMeta.registry[name] = cls
return cls
class Base(metaclass=RegistryMeta):
pass
class Dog(Base):
pass
class Cat(Base):
pass
print(RegistryMeta.registry) # {'Dog': <class '__main__.Dog'>, 'Cat': <class '__main__.Cat'>}
# 2. 强制实现方法
class RequireMethodMeta(type):
def __init__(cls, name, bases, attrs):
required_methods = ["validate", "process"]
for method in required_methods:
if method not in attrs:
raise TypeError(f"子类必须实现 {method} 方法")
super().__init__(name, bases, attrs)
2.12 组合与聚合
概念:组合 vs 继承
- 继承(Is-A):子类是父类的一种,如 Dog is an Animal。适合"是一个"的关系
- 组合(Has-A):类包含另一个类的实例,如 Car has an Engine。适合"有一个"的关系
面向对象设计中,优先使用组合而不是继承,因为组合更灵活、耦合更低。
组合(Has-A)
python
# 组合:一个类包含另一个类的实例
# "拥有"关系,生命周期一致
class Engine:
def start(self):
return "发动机启动"
class Car:
def __init__(self):
self.engine = Engine() # 组合:Car 拥有 Engine
def start(self):
return self.engine.start()
car = Car()
print(car.start()) # 发动机启动
聚合(Uses-A)
python
# 聚合:一个类使用另一个类的实例
# "使用"关系,生命周期独立
class Teacher:
def teach(self):
return " teaching"
class School:
def __init__(self, teacher):
self.teacher = teacher # 聚合:School 使用 Teacher
school = School(Teacher())
组合 vs 继承
python
# 继承(Is-A):"是一个"
# Dog 是 Animal,所以 Dog 继承 Animal
# 组合(Has-A):"有一个"
# Car 有 Engine,所以 Car 包含 Engine
# 优先使用组合,因为:
# 1. 更灵活,可以在运行时替换组件
# 2. 避免继承的脆弱性(父类变化影响子类)
# 3. 减少耦合
常见设计模式
概念:单例模式
单例模式是一种创建型设计模式,确保一个类只有一个实例,并提供全局访问点。常用于配置管理器、数据库连接池、日志器等。
单例模式
python
class Singleton:
_instance = None
def __new__(cls):
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instance
s1 = Singleton()
s2 = Singleton()
print(s1 is s2) # True(同一个对象)
概念:工厂模式
工厂模式是一种创建型设计模式,通过一个工厂类来创建对象,而不是直接使用构造函数。这样可以将对象的创建与使用解耦。
工厂模式
python
class Dog:
def speak(self):
return "汪汪汪"
class Cat:
def speak(self):
return "喵喵喵"
class AnimalFactory:
@staticmethod
def create_animal(animal_type):
if animal_type == "dog":
return Dog()
elif animal_type == "cat":
return Cat()
raise ValueError(f"未知的动物类型: {animal_type}")
animal = AnimalFactory.create_animal("dog")
print(animal.speak()) # 汪汪汪
---
### 概念:观察者模式
观察者模式是一种行为型设计模式,定义了对象间的一对多依赖关系。当一个对象状态改变时,所有依赖它的对象都会收到通知并自动更新。常用于事件系统、消息订阅、GUI 交互等场景。
### 观察者模式
```python
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=None):
for observer in self._observers:
if message:
observer.update(message)
else:
observer.update()
class Observer:
def __init__(self, name):
self.name = name
def update(self, message):
print(f"{self.name} 收到通知: {message}")
# 使用
subject = Subject()
observer1 = Observer("观察者1")
observer2 = Observer("观察者2")
subject.attach(observer1)
subject.attach(observer2)
subject.notify("事件发生了")
# 输出:
# 观察者1 收到通知: 事件发生了
# 观察者2 收到通知: 事件发生了
subject.detach(observer1)
subject.notify("又发生了一件事")
# 输出:
# 观察者2 收到通知: 又发生了一件事
概念:策略模式
策略模式是一种行为型设计模式,定义了算法家族,分别封装起来,让它们可以互相替换。策略模式使算法可以独立于使用它的客户端而变化。常用于排序算法选择、支付方式选择、折扣计算等场景。
策略模式
python
from abc import ABC, abstractmethod
# 抽象策略
class PaymentStrategy(ABC):
@abstractmethod
def pay(self, amount):
pass
# 具体策略
class AlipayStrategy(PaymentStrategy):
def pay(self, amount):
print(f"使用支付宝支付 {amount} 元")
class WechatPayStrategy(PaymentStrategy):
def pay(self, amount):
print(f"使用微信支付 {amount} 元")
class CreditCardStrategy(PaymentStrategy):
def __init__(self, card_number):
self.card_number = card_number
def pay(self, amount):
print(f"使用信用卡 {self.card_number[-4:]} 支付 {amount} 元")
# 上下文
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(self, strategy):
self.payment_strategy = strategy
def checkout(self):
total = sum(price for _, price in self.items)
if self.payment_strategy:
self.payment_strategy.pay(total)
else:
print("请选择支付方式")
# 使用
cart = ShoppingCart()
cart.add_item("商品1", 100)
cart.add_item("商品2", 200)
cart.set_payment(AlipayStrategy())
cart.checkout() # 使用支付宝支付 300 元
cart.set_payment(CreditCardStrategy("1234567890123456"))
cart.checkout() # 使用信用卡 3456 支付 300 元
概念:装饰器模式(进阶)
装饰器模式允许动态地给对象添加职责,比继承更加灵活。它通过将对象包装在装饰器类中,在调用原始对象方法的同时添加新行为。
装饰器模式
python
# 组件接口
class Coffee:
def cost(self):
return 5
# 基础组件
class SimpleCoffee(Coffee):
def cost(self):
return 5
# 装饰器基类
class CoffeeDecorator(Coffee):
def __init__(self, coffee):
self._coffee = coffee
def cost(self):
return self._coffee.cost()
# 具体装饰器
class MilkDecorator(CoffeeDecorator):
def cost(self):
return self._coffee.cost() + 2
class SugarDecorator(CoffeeDecorator):
def cost(self):
return self._coffee.cost() + 1
class WhipDecorator(CoffeeDecorator):
def cost(self):
return self._coffee.cost() + 3
# 使用
coffee = SimpleCoffee()
print(f"美式咖啡: {coffee.cost()}") # 5
coffee_with_milk = MilkDecorator(coffee)
print(f"加奶咖啡: {coffee_with_milk.cost()}") # 7
coffee_with_milk_and_sugar = SugarDecorator(MilkDecorator(coffee))
print(f"加奶加糖: {coffee_with_milk_and_sugar.cost()}") # 8
# 链式装饰
whip_milk_coffee = WhipDecorator(MilkDecorator(SimpleCoffee()))
print(f"奶咖加奶油: {whip_milk_coffee.cost()}") # 10
概念:适配器模式
适配器模式是一种结构型设计模式,用于将一个类的接口转换成客户端期望的另一个接口。适配器让原本接口不兼容的类可以合作无间。
适配器模式
python
# 目标接口
class Target:
def request(self):
return "目标接口的请求"
# 需要适配的类
class Adaptee:
def specific_request(self):
return ".kcapeD tpecretxe si reh troP"
# 类适配器(使用继承)
class ClassAdapter(Adaptee, Target):
def request(self):
result = self.specific_request()
return result[::-1] # 反转字符串
# 对象适配器(使用组合)
class ObjectAdapter(Target):
def __init__(self, adaptee):
self._adaptee = adaptee
def request(self):
result = self._adaptee.specific_request()
return result[::-1]
# 使用
target = Target()
print(target.request()) # 目标接口的请求
adapter1 = ClassAdapter()
print(adapter1.request()) # Python 的是特别好的
adapter2 = ObjectAdapter(Adaptee())
print(adapter2.request()) # Python 的是特别好的
概念:生成器模式
生成器模式是一种创建型设计模式,用于分步骤创建复杂对象。生成器允许使用相同的构建过程创建不同形式的产品。
生成器模式
python
# 产品
class House:
def __init__(self):
self.foundation = None
self.structure = None
self.roof = None
self.interior = None
def __str__(self):
return f"房子: 地基={self.foundation}, 结构={self.structure}, 屋顶={self.roof}, 装修={self.interior}"
# 抽象生成器
class HouseBuilder:
def build_foundation(self):
pass
def build_structure(self):
pass
def build_roof(self):
pass
def build_interior(self):
pass
def get_result(self):
pass
# 具体生成器
class WoodenHouseBuilder(HouseBuilder):
def __init__(self):
self.house = House()
def build_foundation(self):
self.house.foundation = "木质地基"
return self
def build_structure(self):
self.house.structure = "木质框架"
return self
def build_roof(self):
self.house.roof = "木质屋顶"
return self
def build_interior(self):
self.house.interior = "木质装修"
return self
def get_result(self):
return self.house
# 导演
class HouseDirector:
def __init__(self, builder):
self.builder = builder
def construct_simple_house(self):
return (self.builder
.build_foundation()
.build_structure()
.build_roof())
def construct_full_house(self):
return (self.builder
.build_foundation()
.build_structure()
.build_roof()
.build_interior())
# 使用
builder = WoodenHouseBuilder()
director = HouseDirector(builder)
simple_house = director.construct_simple_house()
print(simple_house)
# 房子: 地基=木质地基, 结构=木质框架, 屋顶=木质屋顶, 装修=None
full_house = director.construct_full_house()
print(full_house)
# 房子: 地基=木质地基, 结构=木质框架, 屋顶=木质屋顶, 装修=木质装修
概念:模板方法模式
模板方法模式是一种行为型设计模式,定义算法骨架,将某些步骤推迟到子类中实现。模板方法使子类可以在不改变算法结构的情况下,重新定义算法的某些特定步骤。
模板方法模式
python
from abc import ABC, abstractmethod
# 抽象基类
class DataMiner(ABC):
# 模板方法
def mine(self, path):
file = self.open_file(path)
data = self.extract_data(file)
parsed = self.parse_data(data)
analysis = self.analyze_data(parsed)
self.send_report(analysis)
self.close_file(file)
# 抽象方法(子类必须实现)
@abstractmethod
def open_file(self, path):
pass
@abstractmethod
def extract_data(self, file):
pass
@abstractmethod
def parse_data(self, data):
pass
@abstractmethod
def close_file(self, file):
pass
# 具体方法(子类可以重写)
def analyze_data(self, data):
return f"分析数据: {len(data)} 条记录"
def send_report(self, analysis):
print(f"发送报告: {analysis}")
# 具体实现
class PDFDataMiner(DataMiner):
def open_file(self, path):
print(f"打开 PDF: {path}")
return {"type": "pdf", "path": path}
def extract_data(self, file):
print("从 PDF 提取数据")
return ["数据1", "数据2", "数据3"]
def parse_data(self, data):
print("解析 PDF 数据")
return [d.upper() for d in data]
def close_file(self, file):
print(f"关闭 PDF: {file['path']}")
class CSVDataMiner(DataMiner):
def open_file(self, path):
print(f"打开 CSV: {path}")
return {"type": "csv", "path": path}
def extract_data(self, file):
print("从 CSV 提取数据")
return ["记录A", "记录B"]
def parse_data(self, data):
print("解析 CSV 数据")
return [d.lower() for d in data]
def close_file(self, file):
print(f"关闭 CSV: {file['path']}")
# 使用
print("=== PDF 挖掘 ===")
pdf_miner = PDFDataMiner()
pdf_miner.mine("/path/to/file.pdf")
print("\n=== CSV 挖掘 ===")
csv_miner = CSVDataMiner()
csv_miner.mine("/path/to/file.csv")