Python进阶教程

分类: Python语言

Python进阶教程

目录

  1. 装饰器
  2. 生成器与迭代器
  3. 上下文管理器
  4. 元编程
  5. 并发编程
  6. 异步编程
  7. 数据库操作
  8. 网络编程
  9. 测试与调试
  10. 代码规范与设计模式

一、装饰器

1.1 装饰器基础

装饰器是Python中一种强大的语法糖,它可以在不修改原函数的情况下动态地扩展函数的功能。装饰器本质上是一个接受函数作为参数并返回新函数的高阶函数。

装饰器的核心思想是将函数作为参数传入另一个函数,在原函数执行前后添加额外的功能。这类似于面向切面编程(AOP)的概念,让我们能够在不修改原函数代码的情况下增强其行为。

# 装饰器的基本结构
def my_decorator(func):
    def wrapper(*args, **kwargs):
        # 在函数执行前的操作
        print("函数执行前...")
        # 执行原函数
        result = func(*args, **kwargs)
        # 在函数执行后的操作
        print("函数执行后...")
        return result
    return wrapper

@my_decorator
def say_hello():
    print("Hello!")

# 调用装饰后的函数
say_hello()
# 输出:
# 函数执行前...
# Hello!
# 函数执行后...

在上述代码中,@my_decorator是装饰器语法糖,等价于say_hello = my_decorator(say_hello)。装饰器将原始的say_hello函数替换为wrapper函数,从而在保持原函数功能的基础上添加了额外的行为。

1.2 带参数的装饰器

装饰器可以接受参数来实现更灵活的功能。这需要再包装一层函数来接收参数。

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(times=3)
def greet(name):
    print(f"Hello, {name}!")

greet("张三")
# 输出:Hello, 张三! 三次

这个装饰器工厂模式允许我们在使用装饰器时传递参数。@repeat(times=3)首先调用repeat(3)返回一个装饰器,然后再装饰目标函数。

1.3 保留原函数元信息

使用装饰器后,原函数的元信息(如__name____doc__等)会被覆盖为包装函数的信息。可以使用functools.wraps来保留原函数的信息。

import functools

def my_decorator(func):
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        """这是包装函数"""
        print("执行前")
        result = func(*args, **kwargs)
        print("执行后")
        return result
    return wrapper

@my_decorator
def example():
    """这是原函数的文档字符串"""
    print("原函数执行")

print(example.__name__)    # example(保留原函数名)
print(example.__doc__)     # 这是原函数的文档字符串(保留原文档)

functools.wraps装饰器会自动复制被装饰函数的__name____doc____module____annotations__等属性到包装函数中,确保装饰后的函数保持与原函数相同的元信息。

1.4 类装饰器

装饰器不仅可用于函数,还可用于类。类装饰器可以修改类的行为或为类添加功能。

def singleton(cls):
    """单例模式装饰器"""
    instances = {}

    @functools.wraps(cls)
    def get_instance(*args, **kwargs):
        if cls not in instances:
            instances[cls] = cls(*args, **kwargs)
        return instances[cls]
    return get_instance

@singleton
class Database:
    def __init__(self):
        print("创建数据库连接")

    def query(self, sql):
        return f"执行: {sql}"

# 测试
db1 = Database()
db2 = Database()
print(db1 is db2)  # True(同一个实例)

这个单例装饰器确保一个类只有一个实例,多次实例化返回同一个对象,这在管理共享资源时非常有用。

1.5 常见内置装饰器

Python提供了许多内置装饰器,了解它们有助于编写更好的代码。

装饰器 所属模块 说明
@staticmethod builtins 静态方法装饰器
@classmethod builtins 类方法装饰器
@property builtins 属性装饰器
@functools.wraps functools 保留函数元信息
@functools.lru_cache functools 缓存装饰器
@abstractmethod abc 抽象方法装饰器
class Circle:
    def __init__(self, radius):
        self.radius = radius

    @property
    def diameter(self):
        return self.radius * 2

    @property
    def area(self):
        import math
        return math.pi * self.radius ** 2

circle = Circle(5)
print(circle.diameter)  # 10(作为属性访问)
print(circle.area)      # 78.54(作为属性访问)

@property装饰器允许我们将方法作为属性访问,提供了更直观的API,同时可以在访问器方法中添加计算逻辑。


二、生成器与迭代器

2.1 迭代器协议

迭代器是Python中用于遍历数据集合的对象,它必须实现__iter____next__方法。迭代器协议定义了对象如何被遍历的标准化方式。

__iter__方法返回迭代器对象本身,而__next__方法返回序列中的下一个元素,当没有更多元素时抛出StopIteration异常。

class MyIterator:
    def __init__(self, data):
        self.data = data
        self.index = 0

    def __iter__(self):
        return self

    def __next__(self):
        if self.index >= len(self.data):
            raise StopIteration
        result = self.data[self.index]
        self.index += 1
        return result

# 使用迭代器
my_iter = MyIterator([1, 2, 3, 4, 5])
for item in my_iter:
    print(item)

这个自定义迭代器实现了完整的迭代器协议,可以用在for循环中遍历数据。每次调用__next__都会返回下一个元素,直到数据遍历完毕。

2.2 生成器函数

生成器是一种特殊的迭代器,使用yield关键字来产生值,而不是return。生成器函数在每次调用时执行到yield语句,然后暂停执行,保存当前状态,下次调用时从暂停处继续执行。

生成器提供了一种简洁的方式来创建迭代器,特别适合处理大量数据或无限序列,因为生成器不会一次性将所有数据加载到内存中。

def fibonacci(n):
    """生成斐波那契数列"""
    a, b = 0, 1
    count = 0
    while count < n:
        yield a
        a, b = b, a + b
        count += 1

# 使用生成器
for num in fibonacci(10):
    print(num, end=" ")
# 输出:0 1 1 2 3 5 8 13 21 34

生成器函数会在每次yield时暂停并返回当前值,下次调用时从上次暂停的地方继续执行。这使得生成器非常适合处理大型数据或无限序列,因为我们不需要一次性生成所有数据。

2.3 生成器表达式

生成器表达式类似于列表推导式,但使用圆括号而不是方括号,返回一个生成器对象而不是列表。生成器表达式是创建迭代器的一种简洁方式。

# 列表推导式(立即生成所有元素)
squares_list = [x**2 for x in range(10)]
print(squares_list)  # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

# 生成器表达式(延迟生成,按需计算)
squares_gen = (x**2 for x in range(10))
print(squares_gen)  # <generator object <genexpr> at 0x...>

# 使用next()获取元素
print(next(squares_gen))  # 0
print(next(squares_gen))  # 1

# 在for循环中使用
for sq in squares_gen:
    print(sq)

生成器表达式的优势在于它不会立即计算所有值,而是按需生成,这在处理大型数据集时可以节省大量内存。生成器是惰性求值的,只有当需要时才计算下一个值。

2.4 itertools模块

itertools模块提供了许多用于操作迭代器的函数,是处理序列数据的有力工具。

函数 说明
count(start, step) 无限计数迭代器
cycle(iterable) 无限循环迭代器
repeat(elem, n) 重复元素n次
chain(*iterables) 连接多个迭代器
islice(iterable, start, stop, step) 切片迭代器
tee(iterable, n) 将一个迭代器复制n份
filterfalse(pred, iterable) 过滤不满足条件的元素
accumulate(iterable, func) 累加运算
import itertools

# count - 无限计数
for i in itertools.count(0, 2):
    if i > 10:
        break
    print(i, end=" ")  # 0 2 4 6 8 10

# chain - 连接多个序列
combined = itertools.chain([1, 2], [3, 4], [5])
print(list(combined))  # [1, 2, 3, 4, 5]

# islice - 切片
sliced = itertools.islice(range(10), 2, 8, 2)
print(list(sliced))  # [2, 4, 6]

# tee - 复制迭代器
iter1, iter2 = itertools.tee([1, 2, 3, 4, 5], 2)
print(list(iter1))  # [1, 2, 3, 4, 5]
print(list(iter2))  # [1, 2, 3, 4, 5]

三、上下文管理器

3.1 上下文管理器基础

上下文管理器是一种用于管理资源的协议,确保资源在使用后被正确释放。最常见的应用场景是文件操作,确保文件在使用后被关闭,即使发生异常也能正确关闭。

上下文管理器通过__enter____exit__方法实现。__enter__方法在进入with语句时调用,__exit__方法在离开with语句时调用。

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()
        # 返回True可以抑制异常传播
        return False

# 使用上下文管理器
with FileManager("test.txt", "w") as f:
    f.write("Hello, World!")

# 文件自动关闭

在这个例子中,__enter__方法打开文件并返回文件对象,__exit__方法确保文件被正确关闭。无论with块内是否发生异常,__exit__都会被调用,从而保证资源被正确释放。

3.2 使用contextmanager装饰器

Python的contextlib模块提供了contextmanager装饰器,可以用更简洁的方式创建上下文管理器,而不需要定义完整的类。

from contextlib import contextmanager

@contextmanager
def managed_resource(name):
    """资源管理上下文管理器"""
    print(f"获取资源: {name}")
    resource = f"资源-{name}"
    try:
        yield resource  # 类似于return,将资源提供给with块
    finally:
        print(f"释放资源: {name}")

# 使用
with managed_resource("数据库") as res:
    print(f"使用{res}进行操作")
# 输出:
# 获取资源: 数据库
# 使用资源-数据库进行操作
# 释放资源: 数据库

@contextmanager装饰器允许我们使用yield语句来分隔__enter__(yield之前)和__exit__(yield之后)的代码。这大大简化了上下文管理器的编写,特别适合简单的资源管理场景。

3.3 嵌套上下文管理器

可以使用多个嵌套的with语句或在一个with语句中使用多个上下文管理器。

# 嵌套with语句
with open("file1.txt", "w") as f1:
    with open("file2.txt", "w") as f2:
        f1.write("内容1")
        f2.write("内容2")

# 逗号分隔的多个上下文管理器
with open("file1.txt", "w") as f1, open("file2.txt", "w") as f2:
    f1.write("内容1")
    f2.write("内容2")

# Python 3.10+的括号语法
with (open("file1.txt", "w") as f1,
      open("file2.txt", "w") as f2):
    f1.write("内容1")
    f2.write("内容2")

3.4 常见使用场景

上下文管理器不仅用于文件操作,还广泛应用于需要资源管理或状态恢复的场景。

场景 说明
文件操作 自动关闭文件
数据库连接 自动提交或回滚事务
线程锁 自动获取和释放锁
临时状态 保存和恢复状态
计时 测量代码执行时间
模拟补丁 在测试中临时替换对象
import time
from contextlib import contextmanager

@contextmanager
def timer(name):
    """代码块计时器"""
    start = time.time()
    yield
    end = time.time()
    print(f"{name} 耗时: {end - start:.4f}秒")

# 使用
with timer("数据处理"):
    time.sleep(0.1)
# 输出:数据处理 耗时: 0.1xxx秒

四、元编程

4.1 反射与内省

反射是指在运行时动态获取对象的类型、属性和方法的能力。Python提供了丰富的内置函数和模块来支持反射操作。

函数 说明
type(obj) 获取对象的类型
isinstance(obj, class) 判断对象是否是类的实例
hasattr(obj, name) 判断对象是否有指定属性
getattr(obj, name, default) 获取对象的属性值
setattr(obj, name, value) 设置对象的属性值
delattr(obj, name) 删除对象的属性
callable(obj) 判断对象是否可调用
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def greet(self):
        return f"Hello, I'm {self.name}"

person = Person("张三", 25)

# 反射操作
print(type(person))  # <class '__main__.Person'>
print(isinstance(person, Person))  # True
print(hasattr(person, "name"))  # True
print(getattr(person, "name"))  # 张三
setattr(person, "age", 26)
print(person.age)  # 26
print(callable(person.greet))  # True

反射机制使代码能够在运行时动态地操作对象,这对于构建通用框架、ORM系统、序列化框架等非常有用。

4.2 元类

元类是类的类,用于创建类的工厂。通过元类,我们可以在类定义时动态修改类的行为。

# 简单的元类示例
class Meta(type):
    def __new__(cls, name, bases, attrs):
        # 为每个方法添加前缀
        for key, value in attrs.items():
            if callable(value) and not key.startswith("_"):
                attrs[key] = lambda self, *args, **kwargs: value(self, *args, **kwargs)
        return super().__new__(cls, name, bases, attrs)

class MyClass(metaclass=Meta):
    def method1(self):
        return "方法1"

    def method2(self):
        return "方法2"

obj = MyClass()
print(obj.method1())  # 方法1

元类在框架开发中非常有用,例如Django的ORM系统就使用元类来实现模型类的自动注册。使用元类可以拦截类的创建过程,在类创建之前修改其属性或行为。

4.3 属性描述符

描述符是实现__get____set____delete__方法的对象,用于管理属性的访问。

class PropertyDescriptor:
    """属性描述符示例"""
    def __init__(self, name):
        self.name = name

    def __get__(self, obj, objtype=None):
        return getattr(obj, f"_{self.name}", None)

    def __set__(self, obj, value):
        if value < 0:
            raise ValueError("值不能为负数")
        setattr(obj, f"_{self.name}", value)

    def __delete__(self, obj):
        raise AttributeError("不能删除此属性")

class Rectangle:
    width = PropertyDescriptor("width")
    height = PropertyDescriptor("height")

    def __init__(self, width, height):
        self.width = width
        self.height = height

    def area(self):
        return self.width * self.height

rect = Rectangle(5, 3)
print(rect.area())  # 15
rect.width = 10
print(rect.area())  # 30
rect.width = -5  # 抛出ValueError

属性描述符提供了一种强大的方式来定义属性的行为,实现数据验证、计算属性、只读属性等高级功能。

4.4 动态创建类与函数

在某些高级场景下,需要动态创建类或函数。

# 动态创建函数
def create_adder(n):
    def adder(x):
        return x + n
    return adder

add5 = create_adder(5)
print(add5(10))  # 15

# 动态创建类
def create_class(name):
    return type(name, (), {"value": 10})

MyClass = create_class("MyClass")
obj = MyClass()
print(obj.value)  # 10

五、并发编程

5.1 多线程编程

Python的threading模块提供了多线程编程的支持。多线程适用于I/O密集型任务,如网络请求、文件读写等。

import threading
import time

def worker(name, delay):
    print(f"线程 {name} 开始")
    time.sleep(delay)
    print(f"线程 {name} 结束")

# 创建线程
threads = []
for i in range(3):
    t = threading.Thread(target=worker, args=(f"Thread-{i}", i))
    threads.append(t)
    t.start()

# 等待所有线程完成
for t in threads:
    t.join()

print("所有线程执行完毕")

线程的主要优势在于能够并发执行任务,提高程序的响应性。对于I/O密集型任务,多线程可以显著提高效率,因为线程在等待I/O操作时可以释放GIL(全局解释器锁),允许其他线程执行。

5.2 线程同步

当多个线程共享数据时,需要使用同步机制来避免竞态条件。

机制 说明
Lock 互斥锁,同一时刻只允许一个线程访问
RLock 可重入锁,同一线程可多次获取
Semaphore 信号量,控制同时访问的资源数量
Event 事件,用于线程间通信
Condition 条件变量,用于复杂的线程同步
Queue 队列,生产者-消费者模式
import threading

# 使用Lock保护共享资源
counter = 0
lock = threading.Lock()

def increment():
    global counter
    for _ in range(100000):
        with lock:
            counter += 1

threads = [threading.Thread(target=increment) for _ in range(5)]
for t in threads:
    t.start()
for t in threads:
    t.join()

print(f"最终计数器值: {counter}")  # 500000(正确)

在这个例子中,如果不用Lock保护,counter += 1操作可能会被多个线程同时执行,导致计数不准确。Lock确保了同一时刻只有一个线程能够修改counter

5.3 多进程编程

由于Python的GIL限制,CPU密集型任务应该使用多进程来实现真正的并行计算。multiprocessing模块提供了多进程编程的支持。

import multiprocessing
import time

def cpu_task(n):
    """CPU密集型任务"""
    result = sum(i*i for i in range(n))
    return result

if __name__ == "__main__":
    # 创建进程池
    with multiprocessing.Pool(processes=4) as pool:
        # 并行执行任务
        results = pool.map(cpu_task, [1000000] * 8)
        print(f"结果: {results}")

多进程每个进程有独立的GIL,可以真正并行执行。multiprocessing模块的接口与threading模块类似,但使用的是进程而不是线程。进程间的通信需要使用Queue、Pipe等机制。

5.4 进程间通信

import multiprocessing

def worker(queue):
    """从队列获取数据并处理"""
    while not queue.empty():
        item = queue.get()
        print(f"处理: {item}")
        queue.task_done()

if __name__ == "__main__":
    # 创建队列
    queue = multiprocessing.Queue()

    # 添加任务
    for i in range(5):
        queue.put(i)

    # 启动工作进程
    processes = []
    for _ in range(2):
        p = multiprocessing.Process(target=worker, args=(queue,))
        p.start()
        processes.append(p)

    # 等待完成
    for p in processes:
        p.join()

    print("所有任务处理完毕")

六、异步编程

6.1 异步编程基础

异步编程是一种并发编程范式,允许在等待I/O操作时执行其他任务。Python 3.5+引入了async/await语法,使得异步编程更加简洁。

asyncio是Python的异步编程库,提供了一个事件循环来管理异步任务的执行。

import asyncio

async def fetch_data(url):
    """模拟异步获取数据"""
    print(f"开始获取: {url}")
    await asyncio.sleep(2)  # 模拟网络请求
    print(f"完成获取: {url}")
    return f"数据-{url}"

async def main():
    # 异步任务列表
    urls = ["url1", "url2", "url3"]

    # 并发执行多个异步任务
    tasks = [fetch_data(url) for url in urls]
    results = await asyncio.gather(*tasks)

    print(f"所有结果: {results}")

# 运行异步程序
asyncio.run(main())

异步编程的核心优势在于能够高效地处理大量并发I/O操作,例如网络请求、数据库查询等。与多线程相比,异步编程不需要切换线程的开销,代码更加简洁易读。

6.2 async/await语法

async def用于定义异步函数,await用于等待异步操作完成。

import asyncio

async def async_function():
    """异步函数"""
    print("异步函数开始")
    result = await another_async_function()
    print("异步函数结束")
    return result

async def another_async_function():
    """另一个异步函数"""
    await asyncio.sleep(1)
    return "异步结果"

# 运行
result = asyncio.run(async_function())

await只能在async函数中使用,它暂停当前协程的执行,等待另一个协程完成后再继续执行。这使得我们能够以同步的方式编写异步代码,大大提高了代码的可读性。

6.3 异步迭代器与生成器

import asyncio

class AsyncIterator:
    """异步迭代器"""
    def __init__(self, data):
        self.data = data
        self.index = 0

    def __aiter__(self):
        return self

    async def __anext__(self):
        if self.index >= len(self.data):
            raise StopAsyncIteration
        value = self.data[self.index]
        self.index += 1
        await asyncio.sleep(0.1)  # 模拟异步操作
        return value

async def main():
    async for item in AsyncIterator([1, 2, 3, 4, 5]):
        print(item)

asyncio.run(main())

异步迭代器允许在迭代过程中执行异步操作,这对于处理流式数据特别有用,例如异步读取文件、异步网络请求等场景。

6.4 aiohttp异步HTTP客户端

在异步编程中,aiohttp是常用的异步HTTP客户端库。

import asyncio
import aiohttp

async def fetch_url(session, url):
    async with session.get(url) as response:
        return await response.text()

async def main():
    urls = [
        "https://httpbin.org/get",
        "https://httpbin.org/ip",
        "https://httpbin.org/headers"
    ]

    async with aiohttp.ClientSession() as session:
        tasks = [fetch_url(session, url) for url in urls]
        results = await asyncio.gather(*tasks)

        for url, result in zip(urls, results):
            print(f"{url}: {len(result)} bytes")

asyncio.run(main())

aiohttp能够并发地发起多个HTTP请求,充分利用异步I/O的优势,比同步HTTP客户端效率高得多。


七、数据库操作

7.1 SQLite数据库操作

SQLite是Python内置的轻量级数据库,不需要额外的服务器进程,适合小型项目和快速原型开发。

import sqlite3

# 连接到数据库(不存在则创建)
conn = sqlite3.connect("example.db")
cursor = conn.cursor()

# 创建表
cursor.execute("""
    CREATE TABLE IF NOT EXISTS users (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        name TEXT NOT NULL,
        email TEXT UNIQUE,
        age INTEGER
    )
""")

# 插入数据
cursor.execute("INSERT INTO users (name, email, age) VALUES (?, ?, ?)",
               ("张三", "zhangsan@example.com", 25))

# 批量插入
users = [
    ("李四", "lisi@example.com", 30),
    ("王五", "wangwu@example.com", 28)
]
cursor.executemany("INSERT INTO users (name, email, age) VALUES (?, ?, ?)", users)

# 查询数据
cursor.execute("SELECT * FROM users WHERE age > ?", (25,))
results = cursor.fetchall()
for row in results:
    print(f"ID: {row[0]}, Name: {row[1]}, Email: {row[2]}, Age: {row[3]}")

# 更新数据
cursor.execute("UPDATE users SET age = ? WHERE name = ?", (26, "张三"))

# 删除数据
cursor.execute("DELETE FROM users WHERE name = ?", ("王五",))

# 提交更改并关闭连接
conn.commit()
conn.close()

7.2 使用DB-API

Python的DB-API 2.0是数据库操作的标准化接口,主要方法包括connect()、cursor()、execute()、fetchone()、fetchall()、close()等。

方法 说明
connect() 建立数据库连接
cursor() 创建游标对象
execute() 执行SQL语句
executemany() 批量执行SQL
fetchone() 获取一条记录
fetchall() 获取所有记录
commit() 提交事务
rollback() 回滚事务
close() 关闭连接

7.3 ORM框架简介

ORM(Object-Relational Mapping)将对象映射到数据库表,简化数据库操作。SQLAlchemy是Python最流行的ORM框架之一。

from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.orm import sessionmaker, declarative_base

# 创建引擎
engine = create_engine("sqlite:///example.db", echo=True)

# 定义模型基类
Base = declarative_base()

# 定义模型类
class User(Base):
    __tablename__ = "users"

    id = Column(Integer, primary_key=True)
    name = Column(String(50), nullable=False)
    email = Column(String(50), unique=True)
    age = Column(Integer)

# 创建表
Base.metadata.create_all(engine)

# 创建会话
Session = sessionmaker(bind=engine)
session = Session()

# 插入
new_user = User(name="张三", email="zhangsan@example.com", age=25)
session.add(new_user)
session.commit()

# 查询
user = session.query(User).filter_by(name="张三").first()
print(f"查询结果: {user.name}, {user.email}")

# 更新
user.age = 26
session.commit()

# 删除
session.delete(user)
session.commit()

session.close()

八、网络编程

8.1 socket编程

socket是网络通信的基础,Python的socket模块提供了底层的网络编程接口。

import socket

# 服务器端
def echo_server(host="127.0.0.1", port=8888):
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server_socket.bind((host, port))
    server_socket.listen(5)
    print(f"服务器监听 {host}:{port}")

    while True:
        client_socket, addr = server_socket.accept()
        print(f"收到来自 {addr} 的连接")

        # 接收数据
        data = client_socket.recv(1024)
        print(f"收到数据: {data.decode()}")

        # 发送响应
        client_socket.sendall(b"服务器收到了你的消息")
        client_socket.close()

# 客户端
def echo_client(host="127.0.0.1", port=8888):
    client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    client_socket.connect((host, port))

    message = "Hello, Server!"
    client_socket.sendall(message.encode())

    response = client_socket.recv(1024)
    print(f"服务器响应: {response.decode()}")

    client_socket.close()

socket编程需要处理粘包、半关闭、并发等问题,在生产环境中通常使用更高级的框架。socket.AF_INET表示IPv4,socket.SOCK_STREAM表示TCP协议。

8.2 HTTP服务器

Python的http.server模块提供了简单的HTTP服务器实现。

from http.server import HTTPServer, BaseHTTPRequestHandler

class SimpleHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        self.send_response(200)
        self.send_header("Content-type", "text/html; charset=utf-8")
        self.end_headers()

        response = """
        <!DOCTYPE html>
        <html>
        <head><title>简单HTTP服务器</title></head>
        <body>
            <h1>欢迎访问</h1>
            <p>这是一个简单的HTTP服务器</p>
        </body>
        </html>
        """
        self.wfile.write(response.encode("utf-8"))

    def log_message(self, format, *args):
        print(f"{self.address_string()} - {format % args}")

# 启动服务器
server_address = ("", 8000)
httpd = HTTPServer(server_address, SimpleHandler)
print("服务器运行在 http://localhost:8000")
httpd.serve_forever()

九、测试与调试

9.1 单元测试

unittest是Python内置的单元测试框架。

import unittest

def add(a, b):
    return a + b

def divide(a, b):
    if b == 0:
        raise ValueError("除数不能为零")
    return a / b

class TestMathFunctions(unittest.TestCase):
    def test_add(self):
        self.assertEqual(add(1, 2), 3)
        self.assertEqual(add(-1, 1), 0)
        self.assertEqual(add(0, 0), 0)

    def test_divide(self):
        self.assertEqual(divide(10, 2), 5)
        self.assertEqual(divide(9, 3), 3)

    def test_divide_by_zero(self):
        with self.assertRaises(ValueError):
            divide(10, 0)

if __name__ == "__main__":
    unittest.main()

unittest提供了丰富的断言方法,包括assertEqual、assertTrue、assertFalse、assertIsNone、assertIsNotNone、assertIn、assertRaises等,可以满足大多数测试需求。

9.2 pytest框架

pytest是更现代、更简洁的测试框架,兼容unittest。

# test_example.py

import pytest

def add(a, b):
    return a + b

# 测试函数以test_开头
def test_add():
    assert add(1, 2) == 3
    assert add(-1, 1) == 0
    assert add(0, 0) == 0

# 使用fixture
@pytest.fixture
def sample_data():
    return [1, 2, 3, 4, 5]

def test_sample_data(sample_data):
    assert len(sample_data) == 5
    assert sum(sample_data) == 15

# 参数化测试
@pytest.mark.parametrize("a,b,expected", [
    (1, 2, 3),
    (0, 0, 0),
    (-1, 1, 0),
])
def test_add_parametrized(a, b, expected):
    assert add(a, b) == expected

pytest的fixture机制提供了强大的测试数据管理和依赖注入功能,parametrize装饰器可以轻松实现参数化测试,大大减少测试代码的重复。

9.3 调试技巧

import pdb

def buggy_function(x):
    result = x * 2
    # 设置断点
    pdb.set_trace()
    return result / 0  # 这里会出错

# 使用pdb命令调试:
# n (next) - 执行下一行
# s (step) - 进入函数
# c (continue) - 继续执行
# p variable - 打印变量值
# l (list) - 查看当前代码
# q (quit) - 退出调试

Python还提供了其他调试工具,如ipdb(交互式pdb)、traceback模块(查看异常追溯)、logging模块(日志记录)等。


十、代码规范与设计模式

10.1 PEP 8代码规范

PEP 8是Python的官方代码风格指南,主要规则包括:

规则 说明
缩进 使用4个空格,不要使用Tab
行长度 最多79个字符
空行 类之间两个空行,方法之间一个空行
导入 按标准库、第三方库、本地模块顺序分组
命名 函数和变量用snake_case,类名用PascalCase
空格 避免不必要的空格

可以使用工具自动检查代码规范:pylint、flake8、black(自动格式化)。

10.2 常见设计模式

设计模式是软件工程中常见问题的通用解决方案。

10.2.1 单例模式

class Singleton:
    _instance = None

    def __new__(cls, *args, **kwargs):
        if cls._instance is None:
            cls._instance = super().__new__(cls)
        return cls._instance

s1 = Singleton()
s2 = Singleton()
print(s1 is s2)  # True

10.2.2 工厂模式

class Dog:
    def speak(self):
        return "Woof!"

class Cat:
    def speak(self):
        return "Meow!"

class AnimalFactory:
    @staticmethod
    def create_animal(animal_type):
        animals = {"dog": Dog, "cat": Cat}
        return animals.get(animal_type.lower())()

animal = AnimalFactory.create_animal("dog")
print(animal.speak())  # Woof!

10.2.3 观察者模式

class Subject:
    def __init__(self):
        self._observers = []

    def attach(self, observer):
        self._observers.append(observer)

    def detach(self, observer):
        self._observers.remove(observer)

    def notify(self):
        for observer in self._observers:
            observer.update()

class Observer:
    def update(self):
        print("收到通知")

10.3 虚拟环境最佳实践

# 创建虚拟环境
python -m venv venv

# 激活虚拟环境
# Windows
venv\Scripts\activate
# Linux/Mac
source venv/bin/activate

# 安装依赖
pip install -r requirements.txt

# 导出依赖
pip freeze > requirements.txt

总结

本教程涵盖了Python进阶的核心知识,包括:

  1. 装饰器:函数增强、装饰器工厂、类装饰器
  2. 生成器与迭代器:迭代器协议、生成器函数、itertools
  3. 上下文管理器:资源管理、contextmanager、嵌套上下文
  4. 元编程:反射、元类、属性描述符
  5. 并发编程:多线程、线程同步、多进程
  6. 异步编程:async/await、asyncio、aiohttp
  7. 数据库操作:SQLite、DB-API、SQLAlchemy ORM
  8. 网络编程:socket、HTTP服务器
  9. 测试与调试:unittest、pytest、pdb调试
  10. 代码规范:PEP 8、设计模式

掌握这些进阶知识后,您可以更好地构建复杂的Python应用程序,处理高性能、高并发的场景。持续学习和实践是提升Python技能的关键。