1. Python学习笔记(二):从基础语法到实战技巧
刚接触Python时,我总以为print("Hello World")就是全部。直到真正开始项目开发,才发现数据类型转换的一个小失误就能让程序崩溃,列表推导式的巧妙使用可以节省几十行代码,而装饰器这种看似高级的特性其实每天都在用。这篇笔记记录了我从Python入门到能独立开发小型工具的全过程,特别整理了那些官方文档里不会告诉你的实战经验。
如果你是刚开始学Python的新手,这篇笔记会帮你避开我踩过的所有坑;如果你已经写过一些代码,里面的性能优化技巧和标准库妙用会让你重新认识Python的优雅。我们将从最基础的变量类型开始,逐步深入到文件处理、异常捕获等实用技能,每个知识点都配有可运行的代码示例和真实项目中的应用场景。
2. Python核心语法精要
2.1 变量与数据类型实战
Python的变量看似简单,但类型转换的坑我踩了不止一次。记得有次从API获取的字符串数字直接参与计算,结果抛出TypeError后才明白显式转换的重要:
python复制price = "29.99" # 从网页抓取的价格字符串
# 错误示范:total = price * 0.9
total = float(price) * 0.9 # 必须显式转换
数据类型选择的黄金法则:
- 需要精确计算时用decimal替代float
- 频繁修改的文本用io.StringIO代替直接拼接
- 包含混合数据的集合优先考虑namedtuple
2.2 控制流的高效写法
教科书上的if-else往往过于简单,实际项目中我们经常需要处理多层嵌套。这是我总结的几种优化方案:
python复制# 传统写法
if user.is_authenticated:
if user.has_permission:
if item.in_stock:
process_order()
# 优化方案1:提前返回
if not user.is_authenticated:
return
if not user.has_permission:
return
process_order()
# 优化方案2:使用卫语句
def process_order(user, item):
if not (user.is_authenticated and user.has_permission):
raise PermissionError
if not item.in_stock:
raise InventoryError
# 主逻辑...
循环处理数据时,enumerate和zip的组合能大幅提升可读性:
python复制for idx, (name, score) in enumerate(zip(students, scores), start=1):
print(f"Rank {idx}: {name} - {score}")
3. 函数与模块化编程
3.1 函数设计原则
我早期写的函数经常超过50行,现在严格遵守这些规则:
- 单一职责原则:每个函数只做一件事
- 参数不超过5个,复杂配置用字典或类
- 返回值类型保持一致性
类型注解的实际价值:
python复制def calculate_tax(income: float, brackets: list[tuple[float, float]]) -> float:
"""
:param income: 年收入
:param brackets: 税率区间列表 [(上限, 税率), ...]
:return: 应缴税额
"""
tax = 0.0
for upper, rate in brackets:
if income <= 0:
break
taxable = min(income, upper) if upper else income
tax += taxable * rate
income -= taxable
return tax
3.2 模块组织技巧
经过多个项目迭代,我总结出这样的包结构:
code复制project/
├── core/ # 核心业务逻辑
│ ├── __init__.py
│ ├── models.py
│ └── services.py
├── utils/ # 工具函数
│ ├── date.py
│ └── file.py
├── config.py # 配置管理
└── main.py # 入口文件
关键经验:
- 避免循环导入
- 在__init__.py中暴露主要接口
- 使用if name == 'main'保护测试代码
4. 文件处理与异常管理
4.1 安全文件操作
初学时我经常忘记关闭文件,直到遇到"Too many open files"错误。现在统一使用上下文管理器:
python复制# 传统方式(危险)
f = open('data.txt')
try:
data = f.read()
finally:
f.close()
# Pythonic方式
with open('data.txt', 'r', encoding='utf-8') as f:
data = f.read()
# 自动处理关闭
处理大文件时,逐行读取才是正道:
python复制def count_lines(filename):
with open(filename, 'rb') as f:
return sum(1 for _ in f)
4.2 异常处理最佳实践
从盲目捕获所有异常到精确处理,我经历了这些阶段:
python复制# 初级:捕获所有异常(不推荐)
try:
risky_operation()
except:
pass
# 中级:捕获特定异常
try:
risky_operation()
except (ValueError, IndexError) as e:
log_error(e)
raise CustomError from e
# 高级:上下文管理器封装
class DatabaseConnection:
def __enter__(self):
self.conn = connect_db()
return self.conn
def __exit__(self, exc_type, exc_val, exc_tb):
self.conn.close()
if isinstance(exc_val, DatabaseError):
notify_admin()
return True # 抑制异常
5. 常见问题排查手册
5.1 编码问题
症状:UnicodeDecodeError或乱码
- 解决方案:
- 统一使用utf-8编码
- 文件操作显式指定encoding参数
- 对不可信输入使用errors='replace'
python复制with open('data.txt', 'r', encoding='utf-8', errors='replace') as f:
content = f.read()
5.2 性能问题
场景:列表处理速度慢
- 优化方案:
- 用生成器替代大列表
- 使用map/filter代替循环
- 考虑numpy数组处理数值计算
python复制# 低效
result = []
for x in big_list:
if x > 0:
result.append(x * 2)
# 高效
result = [x * 2 for x in big_list if x > 0]
# 或使用生成器
result_gen = (x * 2 for x in big_list if x > 0)
5.3 模块导入错误
典型错误:ImportError或ModuleNotFoundError
- 排查步骤:
- 检查sys.path是否包含模块路径
- 确认__init__.py文件存在(Python 3.3+可选)
- 避免命名冲突(如模块与标准库同名)
python复制import sys
sys.path.append('/path/to/your/module')
from mypackage import utils # 确保mypackage在sys.path中
6. Pythonic编程进阶技巧
6.1 魔术方法的妙用
实现上下文管理器除了用@contextmanager,还可以直接定义__enter__和__exit__:
python复制class Timer:
def __enter__(self):
self.start = time.perf_counter()
return self
def __exit__(self, *args):
self.elapsed = time.perf_counter() - self.start
print(f"耗时: {self.elapsed:.2f}s")
with Timer() as t:
time.sleep(1.5)
# 自动输出: 耗时: 1.50s
6.2 装饰器实战应用
记录函数执行时间的通用装饰器:
python复制def timer(func):
@functools.wraps(func) # 保留原函数元信息
def wrapper(*args, **kwargs):
start = time.perf_counter()
result = func(*args, **kwargs)
duration = time.perf_counter() - start
print(f"{func.__name__} 执行时间: {duration:.4f}秒")
return result
return wrapper
@timer
def process_data(data):
time.sleep(0.5)
return len(data)
6.3 并发编程模式
线程池处理IO密集型任务的标准模式:
python复制from concurrent.futures import ThreadPoolExecutor
def download_url(url):
# 模拟下载操作
return f"{url} content"
urls = ["url1", "url2", "url3"]
with ThreadPoolExecutor(max_workers=4) as executor:
results = list(executor.map(download_url, urls))
7. 标准库隐藏宝藏
7.1 collections模块
defaultdict自动处理缺失键:
python复制from collections import defaultdict
word_counts = defaultdict(int)
for word in document:
word_counts[word] += 1 # 无需检查key是否存在
Counter快速统计频率:
python复制from collections import Counter
words = ["apple", "banana", "apple", "orange"]
word_counts = Counter(words)
print(word_counts.most_common(1)) # [('apple', 2)]
7.2 itertools技巧
无限迭代器生成测试数据:
python复制import itertools
# 生成测试ID:ID_001, ID_002...
test_ids = (f"ID_{n:03d}" for n in itertools.count(1))
滑动窗口处理序列:
python复制def sliding_window(sequence, n=2):
iterators = itertools.tee(sequence, n)
for i, it in enumerate(iterators):
next(itertools.islice(it, i, i), None)
return zip(*iterators)
list(sliding_window([1,2,3,4], 3)) # [(1,2,3), (2,3,4)]
8. 项目实战:构建配置文件加载器
结合所学知识,我们实现一个健壮的配置加载器:
python复制import json
from pathlib import Path
from typing import TypedDict
class Config(TypedDict):
timeout: float
retries: int
servers: list[str]
DEFAULT_CONFIG: Config = {
"timeout": 3.0,
"retries": 3,
"servers": ["default"]
}
def load_config(config_path: str | Path) -> Config:
"""加载并验证配置文件"""
path = Path(config_path)
if not path.exists():
return DEFAULT_CONFIG
try:
with open(path, 'r', encoding='utf-8') as f:
config = json.load(f)
except (json.JSONDecodeError, UnicodeDecodeError) as e:
raise ValueError(f"Invalid config file: {e}")
# 类型验证
if not all(k in config for k in DEFAULT_CONFIG):
missing = set(DEFAULT_CONFIG) - set(config)
raise ValueError(f"Missing keys: {missing}")
return {**DEFAULT_CONFIG, **config}
这个实现体现了:
- 类型提示(TypedDict)
- 异常处理
- 默认值管理
- 字典合并操作
- Path对象的使用
9. 性能优化实测对比
通过几个常见场景展示不同写法的性能差异:
9.1 字符串拼接
python复制# 低效(每次拼接创建新对象)
s = ""
for chunk in chunks:
s += chunk
# 高效
s = "".join(chunks)
9.2 成员检测
python复制# 列表检测(O(n))
if x in my_list:
pass
# 集合检测(O(1))
if x in my_set:
pass
9.3 属性访问
python复制# 每次点运算都有查找开销
for _ in range(1000000):
obj.method()
# 将方法绑定到局部变量
method = obj.method
for _ in range(1000000):
method()
10. 调试与测试技巧
10.1 更好的print调试
使用rich库增强输出:
python复制from rich import print
user = {"name": "Alice", "age": 25, "skills": ["Python", "SQL"]}
print(user) # 彩色格式化输出
10.2 交互式调试
在代码中插入调试断点:
python复制import pdb
def complex_function():
x = calculate()
pdb.set_trace() # 交互式调试
y = process(x)
return y
10.3 单元测试模式
使用pytest的fixture:
python复制import pytest
@pytest.fixture
def db_connection():
conn = create_test_connection()
yield conn
conn.close()
def test_query(db_connection):
result = db_connection.query("SELECT 1")
assert result == 1
11. 代码质量保障
11.1 静态检查
使用mypy进行类型检查:
bash复制mypy --strict your_module.py
11.2 代码格式化
black自动格式化:
bash复制black your_script.py
11.3 安全扫描
bandit检查安全问题:
bash复制bandit -r your_package/
12. 资源清理模式
确保资源正确释放的几种方式:
python复制# 方式1:try-finally
f = open('file.txt')
try:
# 使用文件
finally:
f.close()
# 方式2:上下文管理器
with open('file.txt') as f:
# 使用文件
# 方式3:atexit注册
import atexit
def cleanup():
# 清理逻辑
pass
atexit.register(cleanup)
13. 跨版本兼容策略
同时支持Python 3.8+的写法:
python复制import sys
from typing import List, Dict, Union
if sys.version_info >= (3, 9):
from collections.abc import Sequence
else:
from typing import Sequence
def process_items(items: Sequence[Union[str, int]]) -> Dict[str, List[int]]:
"""处理字符串和整数混合的序列"""
result = {}
for item in items:
key = str(item)
if key not in result:
result[key] = []
result[key].append(len(key))
return result
14. 异步编程入门
基础async/await示例:
python复制import asyncio
async def fetch_data(url):
print(f"开始获取 {url}")
await asyncio.sleep(1) # 模拟IO操作
print(f"完成获取 {url}")
return f"{url}的数据"
async def main():
tasks = [
fetch_data("url1"),
fetch_data("url2")
]
results = await asyncio.gather(*tasks)
print(results)
asyncio.run(main())
15. 元编程技巧
动态创建类示例:
python复制def make_class(class_name, **kwargs):
"""动态创建带有属性和方法的类"""
def __init__(self, **inner_kwargs):
for k, v in inner_kwargs.items():
setattr(self, k, v)
cls_dict = {'__init__': __init__}
cls_dict.update(kwargs)
return type(class_name, (object,), cls_dict)
Dog = make_class("Dog", bark=lambda self: print("Woof!"))
d = Dog(name="Buddy")
d.bark() # 输出: Woof!
16. 项目结构建议
中型项目推荐结构:
code复制my_project/
├── docs/ # 文档
├── tests/ # 测试代码
│ ├── unit/ # 单元测试
│ └── integration/ # 集成测试
├── src/ # 源代码
│ ├── package/ # 主包
│ │ ├── __init__.py
│ │ ├── core.py # 核心逻辑
│ │ └── utils.py # 工具函数
│ └── scripts/ # 独立脚本
├── requirements.txt # 依赖列表
├── setup.py # 安装配置
└── README.md # 项目说明
关键原则:
- 分离测试代码与生产代码
- 按功能而非类型组织模块
- 入口文件尽量简单
17. 文档字符串标准
遵循PEP 257的文档规范:
python复制def calculate_stats(data):
"""计算数据的统计特征
Args:
data: 可迭代的数值数据,不能为空
Returns:
dict: 包含以下键的字典:
- mean (float): 平均值
- median (float): 中位数
- stdev (float): 标准差
Raises:
ValueError: 当输入数据为空时抛出
"""
if not data:
raise ValueError("数据不能为空")
sorted_data = sorted(data)
n = len(data)
return {
"mean": sum(data) / n,
"median": (sorted_data[n//2] + sorted_data[(n-1)//2]) / 2,
"stdev": (sum((x - (sum(data)/n))**2 for x in data) / n)**0.5
}
18. 依赖管理实践
使用pip-tools管理依赖:
- 创建requirements.in:
code复制requests>=2.25.0
pandas
- 编译为requirements.txt:
bash复制pip-compile requirements.in
- 同步安装:
bash复制pip-sync requirements.txt
优势:
- 精确锁定版本
- 自动处理子依赖
- 保持开发与生产环境一致
19. 日志配置模板
生产级日志配置:
python复制import logging
from logging.handlers import RotatingFileHandler
def setup_logging(name):
logger = logging.getLogger(name)
logger.setLevel(logging.DEBUG)
# 控制台输出
console = logging.StreamHandler()
console.setLevel(logging.INFO)
console.setFormatter(logging.Formatter(
'%(asctime)s - %(name)s - %(levelname)s - %(message)s'
))
# 文件输出(自动轮转)
file = RotatingFileHandler(
'app.log', maxBytes=10*1024*1024, backupCount=5
)
file.setLevel(logging.DEBUG)
file.setFormatter(logging.Formatter(
'%(asctime)s - %(name)s - %(levelname)s - %(pathname)s:%(lineno)d - %(message)s'
))
logger.addHandler(console)
logger.addHandler(file)
return logger
20. 代码审查要点
我参与的代码审查中常见问题:
-
魔法数字:用常量替代直接使用的数字
python复制# 不好 if status == 1: # 好 ACTIVE = 1 if status == ACTIVE: -
过度嵌套:使用早返模式减少嵌套层级
-
重复代码:提取公共函数或使用装饰器
-
异常滥用:用普通条件判断处理预期内的分支
-
缺乏文档:关键函数缺少docstring和类型提示
21. 性能分析指南
使用cProfile分析代码:
python复制import cProfile
def slow_function():
# 待分析的函数
pass
# 运行分析
profiler = cProfile.Profile()
profiler.enable()
slow_function()
profiler.disable()
profiler.print_stats(sort='cumulative')
关键指标解读:
- ncalls:调用次数
- tottime:函数内部耗时(不含子调用)
- cumtime:包含子调用的总耗时
22. 内存优化技巧
处理大数据时的内存管理:
-
使用生成器替代列表
python复制# 消耗内存 data = [x for x in range(10**6)] # 节省内存 data = (x for x in range(10**6)) -
使用__slots__减少对象内存占用
python复制class Point: __slots__ = ('x', 'y') def __init__(self, x, y): self.x = x self.y = y -
及时释放大对象
python复制big_data = get_huge_data() process(big_data) del big_data # 显式释放
23. 多环境配置方案
处理开发/测试/生产环境的配置:
python复制import os
class Config:
DEBUG = False
TESTING = False
class DevelopmentConfig(Config):
DEBUG = True
DATABASE_URI = 'sqlite:///dev.db'
class ProductionConfig(Config):
DATABASE_URI = os.getenv('DATABASE_URL')
def get_config():
env = os.getenv('FLASK_ENV', 'development')
return {
'development': DevelopmentConfig,
'production': ProductionConfig
}[env]
24. 测试覆盖率实践
使用pytest-cov测量覆盖率:
bash复制pytest --cov=my_package tests/
生成HTML报告:
bash复制pytest --cov=my_package --cov-report=html tests/
覆盖率目标:
- 关键业务逻辑:100%
- 工具函数:90%+
- 边缘情况:至少有一个测试用例
25. 持续集成配置
GitHub Actions示例配置:
yaml复制name: CI
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: '3.9'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
pip install pytest pytest-cov
- name: Run tests
run: |
pytest --cov=./ --cov-report=xml
- name: Upload coverage
uses: codecov/codecov-action@v1
26. 打包发布流程
使用setuptools打包:
python复制# setup.py
from setuptools import setup, find_packages
setup(
name="my_package",
version="0.1.0",
packages=find_packages(where="src"),
package_dir={"": "src"},
install_requires=[
'requests>=2.25.0',
'click>=7.0',
],
entry_points={
'console_scripts': [
'mycli=my_package.cli:main',
],
},
)
发布到PyPI:
bash复制python setup.py sdist bdist_wheel
twine upload dist/*
27. 命令行工具开发
使用click创建CLI:
python复制import click
@click.group()
def cli():
pass
@cli.command()
@click.option('--count', default=1, help='执行次数')
@click.argument('name')
def greet(count, name):
"""向某人问好"""
for _ in range(count):
click.echo(f"Hello, {name}!")
if __name__ == '__main__':
cli()
高级特性:
- 自动生成帮助文档
- 参数类型自动转换
- 彩色输出支持
- 子命令嵌套
28. 网络请求最佳实践
使用requests的高级技巧:
python复制import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry
# 配置重试策略
retry_strategy = Retry(
total=3,
backoff_factor=1,
status_forcelist=[408, 429, 500, 502, 503, 504]
)
# 创建会话
session = requests.Session()
adapter = HTTPAdapter(max_retries=retry_strategy)
session.mount("https://", adapter)
session.mount("http://", adapter)
# 带超时和错误处理的请求
try:
response = session.get(
'https://api.example.com/data',
timeout=(3.05, 27), # 连接超时和读取超时
headers={'User-Agent': 'MyApp/1.0'}
)
response.raise_for_status()
data = response.json()
except requests.exceptions.RequestException as e:
print(f"请求失败: {e}")
29. 数据处理模式
使用pandas的高效操作:
python复制import pandas as pd
# 避免逐行操作,使用向量化
df = pd.read_csv('data.csv')
# 慢:逐行应用
# df['new_col'] = df.apply(lambda row: process_row(row), axis=1)
# 快:向量化操作
df['new_col'] = df['value'] * 1.1
# 更快:使用eval
df.eval('new_col = value * 1.1', inplace=True)
# 分组聚合优化
result = df.groupby('category').agg({
'value': ['sum', 'mean'],
'quantity': 'count'
})
30. 可视化技巧
使用matplotlib和seaborn:
python复制import matplotlib.pyplot as plt
import seaborn as sns
# 设置样式
sns.set_theme(style="whitegrid")
# 创建图形
fig, ax = plt.subplots(figsize=(10, 6))
# 绘制数据
sns.lineplot(
data=df,
x='date',
y='value',
hue='category',
ax=ax,
estimator='median',
errorbar=('pi', 50) # 显示百分位区间
)
# 优化布局
plt.xticks(rotation=45)
fig.tight_layout()
# 保存图像
fig.savefig('plot.png', dpi=300, bbox_inches='tight')
31. 数据库交互模式
使用SQLAlchemy ORM:
python复制from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
Base = declarative_base()
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
name = Column(String(50))
email = Column(String(120), unique=True)
# 创建引擎和会话
engine = create_engine('sqlite:///users.db')
Session = sessionmaker(bind=engine)
session = Session()
# 查询示例
active_users = session.query(User).filter(
User.last_login > datetime.now() - timedelta(days=30)
).order_by(
User.name.asc()
).limit(10).all()
32. 缓存优化策略
使用functools.lru_cache:
python复制from functools import lru_cache
@lru_cache(maxsize=128)
def expensive_calculation(n):
print(f"计算 {n}...")
return n * n # 模拟复杂计算
# 第一次调用会执行计算
print(expensive_calculation(5)) # 输出: 计算 5... \n 25
# 相同参数再次调用直接返回缓存结果
print(expensive_calculation(5)) # 直接输出: 25
高级技巧:
- 对纯函数使用缓存
- 根据内存情况调整maxsize
- 使用cache_clear()在数据变更时清除缓存
33. 日期时间处理
使用pendulum替代datetime:
python复制import pendulum
# 创建时区感知的时间
now = pendulum.now('Asia/Shanghai')
# 人性化操作
tomorrow = now.add(days=1)
last_week = now.subtract(weeks=1)
# 格式化输出
print(now.to_iso8601_string()) # 2023-07-20T14:30:00+08:00
print(now.format('dddd, MMMM Do YYYY [at] h:mm A')) # Thursday, July 20th 2023 at 2:30 PM
# 解析字符串
dt = pendulum.parse('2023-07-20T14:30:00+08:00')
34. 正则表达式优化
编译正则提升性能:
python复制import re
# 预编译正则
PHONE_REGEX = re.compile(r'^1[3-9]\d{9}$')
def validate_phone(number):
return bool(PHONE_REGEX.match(number))
# 使用verbose模式编写复杂正则
MULTILINE_REGEX = re.compile(r"""
^ # 行首
(\w+) # 第一个单词
\s+ # 空白字符
(\d{4}-\d{2}-\d{2}) # 日期
\s+
(.*?) # 任意字符(非贪婪)
$ # 行尾
""", re.VERBOSE | re.MULTILINE)
35. 配置管理方案
使用pydantic验证配置:
python复制from pydantic import BaseSettings, Field
class Settings(BaseSettings):
api_key: str = Field(..., env='API_KEY')
timeout: float = Field(10.0, gt=0)
retries: int = Field(3, ge=0, le=5)
class Config:
env_file = '.env'
env_file_encoding = 'utf-8'
# 自动从环境变量和.env文件加载
settings = Settings()
36. 安全编程要点
常见安全防护措施:
-
SQL注入防护:
python复制# 错误:直接拼接SQL # cursor.execute(f"SELECT * FROM users WHERE name='{name}'") # 正确:使用参数化查询 cursor.execute("SELECT * FROM users WHERE name=%s", (name,)) -
密码哈希:
python复制from werkzeug.security import generate_password_hash hashed_pw = generate_password_hash('mypassword') -
输入净化:
python复制import html user_input = "<script>alert('xss')</script>" safe_output = html.escape(user_input)
37. 设计模式应用
实现策略模式:
python复制from typing import Protocol
class PaymentStrategy(Protocol):
def pay(self, amount: float) -> bool:
...
class CreditCardPayment:
def pay(self, amount: float) -> bool:
print(f"信用卡支付 {amount} 元")
return True
class AlipayPayment:
def pay(self, amount: float) -> bool:
print(f"支付宝支付 {amount} 元")
return True
class PaymentProcessor:
def __init__(self, strategy: PaymentStrategy):
self._strategy = strategy
def process_payment(self, amount: float) -> bool:
return self._strategy.pay(amount)
# 使用
processor = PaymentProcessor(CreditCardPayment())
processor.process_payment(100.0)
38. 代码生成技巧
使用jinja2生成代码:
python复制from jinja2 import Template
template = Template("""
class {{ class_name }}:
def __init__(self, {{ params }}):
{% for param in param_list %}
self.{{ param }} = {{ param }}
{% endfor %}
""")
code = template.render(
class_name="Person",
params="name, age",
param_list=["name", "age"]
)
print(code)
输出:
code复制class Person:
def __init__(self, name, age):
self.name = name
self.age = age
39. 性能敏感代码优化
使用numba加速数值计算:
python复制from numba import njit
import numpy as np
@njit
def monte_carlo_pi(n_samples):
count = 0
for _ in range(n_samples):
x, y = np.random.random(), np.random.random()
if x**2 + y**2 < 1:
count += 1
return 4 * count / n_samples
# 第一次调用会编译函数
print(monte_carlo_pi(1_000_000)) # 3.141...
40. 跨语言交互
使用ctypes调用C函数:
c复制// libexample.c
#include <stdio.h>
void greet(const char *name) {
printf("Hello, %s!\n", name);
}
编译为共享库:
bash复制gcc -shared -o libexample.so -fPIC libexample.c
Python调用:
python复制from ctypes import CDLL, c_char_p
lib = CDLL('./libexample.so')
lib.greet.argtypes = [c_char_p]
lib.greet.restype = None
lib.greet(b"World") # 输出: Hello, World!
41. 调试技巧进阶
使用icecream增强调试:
python复制from icecream import ic
def factorial(n):
ic(n) # 自动打印变量名和值
if n <= 1:
return 1
return n * factorial(n - 1)
ic(factorial(5))
输出:
code复制ic| n: 5
ic| n: 4
ic| n: 3
ic| n: 2
ic| n: 1
ic| factorial(5): 120
42. 测试数据生成
使用faker创建测试数据:
python复制from faker import Faker
fake = Faker('zh_CN')
users = [{
'name': fake.name(),
'email': fake.email(),
'address': fake.address(),
'phone': fake.phone_number()
} for _ in range(10)]
43. 协程高级模式
使用asyncio.Semaphore控制并发:
python复制import asyncio
async def worker(sem, url):
async with sem:
print(f"开始获取 {url}")
await asyncio.sleep(1) # 模拟IO
print(f"完成获取 {url}")
async def main():
sem = asyncio.Semaphore(3) # 最大并发数
tasks = [
worker(sem, f"url-{i}")
for i in range(10)
]
await asyncio.gather(*tasks)
asyncio.run(main())
44. 动态导入技术
按需加载模块:
python复制import importlib
def load_plugin(plugin_name):
try:
module = importlib.import_module(f"plugins.{plugin_name}")
return module.Plugin()
except (ImportError, AttributeError) as e:
print(f"加载插件失败: {e}")
return None
# 使用
plugin = load_plugin("csv_processor")
if plugin:
plugin.run()
45. 代码质量工具集成
pre-commit配置示例:
yaml复制# .pre-commit-config.yaml
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.3.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- repo: https://github.com/psf/black
rev: 22.6.0
hooks:
- id: black
- repo: https://github.com/PyCQA/flake8
rev: 5.0.4
hooks:
- id: fl
