1. Python 函数基础:从零开始理解代码封装
1.1 为什么我们需要函数?
在编程世界里,函数就像厨房里的多功能料理机。想象一下,如果你每次做果汁都要重新组装一次榨汁机,那该有多麻烦?函数的作用就是让我们把常用的功能"封装"起来,需要时直接调用即可。
我刚开始学编程时也不理解函数的意义,直到有次需要反复计算圆的面积。第一次我写了这样的代码:
python复制radius = 5
area = 3.14 * radius ** 2
print(area)
radius = 8
area = 3.14 * radius ** 2
print(area)
radius = 12
area = 3.14 * radius ** 2
print(area)
很快我就发现这样写既冗长又容易出错。后来改用函数:
python复制def circle_area(radius):
return 3.14 * radius ** 2
print(circle_area(5))
print(circle_area(8))
print(circle_area(12))
代码立刻变得简洁明了,这就是函数的魅力。
1.2 函数定义与调用的正确姿势
定义函数时,def关键字就像在说:"我要创建一个新工具"。函数名应该像这个工具的标签,让人一看就知道用途。比如calculate_bmi就比func1清晰得多。
新手常犯的错误是定义了函数却忘记调用。记住:函数定义只是"制作工具",调用才是"使用工具"。我见过不少学员写了漂亮的函数,最后却疑惑为什么没有输出结果。
一个实用的技巧:在PyCharm等IDE中,函数调用处会有特殊颜色提示。如果没有看到任何调用,那你的函数就只是"摆设"。
1.3 返回值:函数的"产出物"
return语句是函数的核心。没有return的函数就像没有出口的迷宫,进去了却得不到任何结果。来看一个典型错误案例:
python复制def add(a, b):
result = a + b
sum = add(3, 5)
print(sum) # 输出None
这里用户期望得到8,实际却是None。因为函数没有return语句,Python默认返回None。
经验之谈:每个函数都应该有明确的返回值。即使不需要返回具体数据,也最好返回True/False表示执行状态。
2. 函数参数的艺术:让接口更灵活
2.1 形参与实参:角色扮演游戏
理解形参和实参的区别很重要。形参是函数定义时的"占位符",实参是调用时传入的"具体值"。就像剧本中的角色和实际演员的关系。
一个常见误区是混淆两者:
python复制def greet(name): # name是形参
print(f"Hello {name}")
greet("Alice") # "Alice"是实参
很多初学者会问:"为什么我在函数外部访问不到name变量?"因为name只在函数内部有效,这就是作用域的概念。
2.2 默认参数的妙用
默认参数就像函数的"备选方案"。我在开发Web应用时经常这样用:
python复制def connect_db(host="localhost", port=3306, user="admin"):
print(f"连接到 {host}:{port} 用户 {user}")
这样大多数情况下只需connect_db(),特殊场景才需要指定参数。
注意事项:默认参数必须放在参数列表最后。Python不允许非默认参数跟在默认参数后面。
2.3 *args和**kwargs:参数收纳专家
当你不确定会收到多少参数时,可变参数就派上用场了。*args接收任意数量的位置参数,**kwargs接收关键字参数。
实际项目中,我常用这种方式处理日志:
python复制def log_message(level, *args, **kwargs):
timestamp = kwargs.get('timestamp', datetime.now())
print(f"[{timestamp}] {level}:", *args)
log_message("INFO", "用户登录成功", timestamp="2023-01-01")
log_message("ERROR", "数据库连接失败", "重试中...")
这种设计让函数既灵活又保持可读性。
3. 变量作用域:避免命名冲突的战场
3.1 全局变量的陷阱
全局变量就像公共场所的公告板,谁都能修改。我曾在一个项目中因为滥用全局变量吃尽苦头:
python复制counter = 0
def increment():
global counter
counter += 1
def reset():
global counter
counter = 0
随着代码增长,很难追踪counter在哪里被修改。后来我改用类来封装状态,问题才解决。
3.2 局部变量的安全性
局部变量是函数的"私有财产",外部无法访问。这是好事,但也可能导致一些困惑:
python复制def calculate():
result = 42 # 局部变量
return result
print(result) # 报错:name 'result' is not defined
正确的做法是通过返回值获取结果:
python复制value = calculate()
print(value) # 正确输出42
3.3 可变对象的特殊行为
列表、字典等可变对象在函数中的表现很特殊:
python复制def add_item(lst, item):
lst.append(item)
my_list = [1, 2, 3]
add_item(my_list, 4)
print(my_list) # [1, 2, 3, 4]
虽然没使用global,但原列表被修改了。这是因为函数接收到的是对象的引用,而非副本。
避坑指南:如果不希望函数修改原列表,可以传入副本:add_item(my_list.copy(), 4)
4. 模块化编程:像搭积木一样写代码
4.1 import的多种姿势
Python提供了灵活的模块导入方式。根据我的经验,每种方式适合不同场景:
- import math - 适合大型标准库,避免命名冲突
- from math import sqrt - 适合频繁使用的函数
- from utils import * - 不推荐,容易导致命名冲突
我曾经在一个项目中使用from x import *,结果两个模块都有open函数,导致难以调试的错误。
4.2 __name__的妙用
这个特殊变量在编写可复用模块时非常有用。我通常这样组织代码:
python复制# my_module.py
def helper_function():
pass
def main():
# 测试代码
pass
if __name__ == '__main__':
main()
这样既可以直接运行测试,又能在被导入时不执行测试代码。
5. 高阶函数技巧:提升代码表现力
5.1 lambda:匿名但有用
lambda就像一次性工具,用完即弃。适合简单操作:
python复制names = ['Alice', 'Bob', 'Charlie']
sorted_names = sorted(names, key=lambda x: len(x))
但复杂的逻辑还是应该用def定义正规函数。我曾经见过有人用lambda写了几十行的"一行代码",那简直是灾难。
5.2 递归:优雅但危险
递归能优雅地解决某些问题,比如计算阶乘:
python复制def factorial(n):
return 1 if n <= 1 else n * factorial(n-1)
但在Python中递归深度有限制(默认1000),而且性能不如循环。我曾经用递归处理大型目录结构,结果遇到栈溢出。
实用建议:在Python中,能用循环解决的问题就不要用递归。
5.3 闭包:记住状态的函数
闭包是可以访问非全局作用域变量的函数。比如:
python复制def make_multiplier(factor):
def multiplier(x):
return x * factor
return multiplier
double = make_multiplier(2)
print(double(5)) # 10
我在实现装饰器时经常使用闭包。它就像给函数添加了"记忆"能力。
6. 函数最佳实践:来自实战的经验
6.1 函数应该有多长?
根据我的经验,一个函数最好能在一屏内完整显示(约20-30行)。如果函数太长,说明它可能做了太多事情。
我曾经重构过一个200行的函数,把它拆分成5个小函数后,代码可读性大幅提升,也更容易测试了。
6.2 参数数量控制
心理学研究表明,人类短期记忆只能保存7±2个信息块。因此函数参数最好不超过5个。如果参数太多,考虑:
- 使用对象封装相关参数
- 拆分函数
- 使用**kwargs接收配置项
6.3 文档字符串的重要性
好的文档字符串(docstring)能让函数自解释。我遵循这样的格式:
python复制def calculate_tax(income, rate):
"""计算应缴税款
Args:
income (float): 年收入
rate (float): 税率(0-1之间)
Returns:
float: 计算结果
"""
return income * rate
这样其他开发者(包括未来的你)能快速理解函数用途。
7. 调试函数的技巧
7.1 打印调试法
在复杂函数中,我经常临时添加print语句:
python复制def complex_calculation(a, b):
print(f"输入参数: a={a}, b={b}")
intermediate = step1(a)
print(f"第一步结果: {intermediate}")
result = step2(intermediate, b)
print(f"最终结果: {result}")
return result
虽然原始,但在某些场景下非常有效。
7.2 使用断言
断言(assert)是预防错误的利器:
python复制def divide(a, b):
assert b != 0, "除数不能为零"
return a / b
这样能在开发阶段快速发现问题。不过生产环境应该用更完善的错误处理。
7.3 日志记录
对于长期运行的程序,使用logging模块更专业:
python复制import logging
logging.basicConfig(level=logging.INFO)
def process_data(data):
logging.info("开始处理数据")
try:
result = complex_operation(data)
logging.info(f"处理成功,结果: {result}")
return result
except Exception as e:
logging.error(f"处理失败: {str(e)}")
raise
这样可以在不中断程序的情况下跟踪执行流程。
8. 性能优化小贴士
8.1 避免重复计算
如果函数中有不变的计算,可以提到函数外部:
python复制# 不推荐
def calculate(x):
constants = load_constants() # 每次调用都执行
return x * constants['factor']
# 推荐
CONSTANTS = load_constants() # 只执行一次
def calculate(x):
return x * CONSTANTS['factor']
我在处理大型数据集时,这个优化曾让程序速度提升10倍。
8.2 使用缓存
对于计算密集型函数,可以使用functools.lru_cache:
python复制from functools import lru_cache
@lru_cache(maxsize=128)
def fibonacci(n):
if n < 2:
return n
return fibonacci(n-1) + fibonacci(n-2)
这个装饰器会自动缓存结果,避免重复计算。
8.3 选择合适的数据结构
函数内部使用的数据结构对性能影响很大。比如成员检查:
python复制# 列表:O(n)时间复杂度
def is_in_list(value, lst):
return value in lst # 线性搜索
# 集合:O(1)时间复杂度
def is_in_set(value, s):
return value in s # 哈希查找
在处理大数据量时,这种差异会非常明显。
9. 函数式编程风格
9.1 map/filter/reduce
这些函数式工具可以让代码更简洁:
python复制numbers = [1, 2, 3, 4, 5]
# 传统方式
squares = []
for n in numbers:
squares.append(n ** 2)
# 函数式风格
squares = list(map(lambda x: x**2, numbers))
不过要注意,过度使用会使代码难以理解。我一般只在简单转换时使用。
9.2 列表推导式
对于简单的映射和过滤,列表推导式通常更Pythonic:
python复制# 等价于上面的map示例
squares = [x**2 for x in numbers]
# 带条件的过滤
evens = [x for x in numbers if x % 2 == 0]
这是我日常最常用的特性之一。
9.3 生成器表达式
处理大数据集时,生成器可以节省内存:
python复制# 列表推导式:立即计算所有结果
big_list = [x**2 for x in range(1000000)] # 占用大量内存
# 生成器表达式:惰性计算
big_gen = (x**2 for x in range(1000000)) # 几乎不占内存
我在处理CSV文件或数据库查询结果时经常使用生成器。
10. 类型提示:让函数接口更清晰
Python 3.5+支持类型提示,虽然不是强制的,但能大大提升代码可维护性:
python复制from typing import List, Tuple
def process_items(items: List[str], count: int) -> Tuple[bool, int]:
"""处理字符串列表
Args:
items: 待处理的字符串列表
count: 最大处理数量
Returns:
元组:(是否成功, 实际处理数量)
"""
# 函数实现
return True, len(items[:count])
使用mypy等工具可以在运行前检查类型错误。我在团队项目中强制要求所有公共函数都添加类型提示,显著减少了接口错误。
11. 装饰器:增强函数功能
装饰器是Python最强大的特性之一,本质上是一个返回函数的高阶函数:
python复制def log_time(func):
import time
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
end = time.time()
print(f"{func.__name__} 执行时间: {end-start:.4f}秒")
return result
return wrapper
@log_time
def slow_function():
time.sleep(1)
slow_function() # 会自动打印执行时间
我在实际项目中使用装饰器实现了很多功能:权限检查、缓存、重试逻辑等。
12. 异步函数:现代Python必备技能
随着asyncio的普及,异步编程变得越来越重要:
python复制import asyncio
async def fetch_data(url):
print(f"开始获取 {url}")
await asyncio.sleep(2) # 模拟IO操作
print(f"完成获取 {url}")
return f"{url}的数据"
async def main():
tasks = [
fetch_data("url1"),
fetch_data("url2"),
fetch_data("url3")
]
results = await asyncio.gather(*tasks)
print(results)
asyncio.run(main())
异步函数可以显著提高IO密集型应用的性能。我在Web爬虫和API服务中大量使用。
13. 单元测试:保证函数质量
为函数编写测试是专业开发的基本要求:
python复制import unittest
def add(a, b):
return a + b
class TestAdd(unittest.TestCase):
def test_add_positive(self):
self.assertEqual(add(2, 3), 5)
def test_add_negative(self):
self.assertEqual(add(-1, -1), -2)
def test_add_zero(self):
self.assertEqual(add(0, 0), 0)
if __name__ == '__main__':
unittest.main()
我坚持为所有关键函数编写测试,这帮助我在重构时保持信心。
14. 函数设计模式
14.1 策略模式
用函数实现策略模式非常简单:
python复制def strategy_add(a, b):
return a + b
def strategy_multiply(a, b):
return a * b
def execute_strategy(strategy, a, b):
return strategy(a, b)
print(execute_strategy(strategy_add, 3, 5)) # 8
print(execute_strategy(strategy_multiply, 3, 5)) # 15
这种模式在实现不同算法时非常有用。
14.2 工厂模式
函数也可以作为对象工厂:
python复制def create_greeter(greeting):
def greeter(name):
print(f"{greeting}, {name}!")
return greeter
say_hello = create_greeter("Hello")
say_hi = create_greeter("Hi")
say_hello("Alice") # Hello, Alice!
say_hi("Bob") # Hi, Bob!
我在实现多语言支持时经常使用这种模式。
15. 函数与面向对象
15.1 类方法 vs 函数
有时候选择用函数还是类方法是个难题。我的经验法则是:
- 如果操作需要维护状态 → 用类
- 如果是独立工具函数 → 用模块级函数
比如字符串处理:
python复制# 作为函数
def reverse_string(s):
return s[::-1]
# 作为类方法
class StringUtils:
@staticmethod
def reverse(s):
return s[::-1]
两种方式都可以,取决于项目风格。
15.2 call 魔法方法
让对象可以像函数一样调用:
python复制class Adder:
def __init__(self, n):
self.n = n
def __call__(self, x):
return self.n + x
add5 = Adder(5)
print(add5(3)) # 8
这种技巧在创建有状态的函数时很有用。
16. 函数性能分析
使用cProfile模块可以分析函数性能:
python复制import cProfile
def slow_function():
total = 0
for i in range(100000):
total += i
return total
cProfile.run('slow_function()')
输出会显示函数调用次数和执行时间,帮助找到性能瓶颈。
17. 函数与并发
17.1 多线程
使用threading模块执行函数:
python复制import threading
def worker(num):
print(f"Worker {num} 开始")
# 做一些工作
print(f"Worker {num} 结束")
threads = []
for i in range(5):
t = threading.Thread(target=worker, args=(i,))
threads.append(t)
t.start()
for t in threads:
t.join()
适合IO密集型任务。
17.2 多进程
对于CPU密集型任务,multiprocessing更合适:
python复制from multiprocessing import Process
def cpu_intensive(n):
return sum(i*i for i in range(n))
if __name__ == '__main__':
with Pool(4) as p:
results = p.map(cpu_intensive, [1000000]*10)
可以充分利用多核CPU。
18. 函数与元编程
18.1 动态创建函数
有时候我们需要在运行时创建函数:
python复制def create_power_function(exponent):
def power(base):
return base ** exponent
return power
square = create_power_function(2)
cube = create_power_function(3)
print(square(5)) # 25
print(cube(5)) # 125
这种技术在实现DSL时很有用。
18.2 函数自省
Python函数有很多有用的属性:
python复制def example(a, b=1, *args, **kwargs):
pass
print(example.__name__) # "example"
print(example.__defaults__) # (1,)
print(example.__code__.co_varnames) # ('a', 'b', 'args', 'kwargs')
这些元信息在框架开发中经常使用。
19. 函数与异常处理
良好的错误处理能让函数更健壮:
python复制def divide(a, b):
try:
return a / b
except ZeroDivisionError:
print("错误:除数不能为零")
return None
except TypeError:
print("错误:参数类型不正确")
return None
我习惯在函数开头验证参数,尽早抛出异常:
python复制def process_data(data):
if not isinstance(data, dict):
raise ValueError("data必须是字典")
if 'required_field' not in data:
raise KeyError("缺少required_field")
# 正常处理逻辑
这样能快速定位问题。
20. 函数与文档生成
良好的文档字符串可以自动生成API文档。我使用Sphinx的Google风格:
python复制def calculate_interest(principal, rate, years):
"""计算复利
Args:
principal (float): 本金
rate (float): 年利率(0-1之间)
years (int): 年数
Returns:
float: 最终金额
Examples:
>>> calculate_interest(1000, 0.05, 10)
1628.894626777442
"""
return principal * (1 + rate) ** years
这种文档可以通过工具自动转换为漂亮的HTML文档。
21. 函数与包管理
当函数越来越多时,应该组织成包:
code复制my_package/
__init__.py
utils.py
math/
__init__.py
stats.py
geometry.py
然后在__init__.py中暴露主要接口:
python复制# my_package/math/__init__.py
from .geometry import circle_area
from .stats import mean, median
__all__ = ['circle_area', 'mean', 'median']
这样用户可以通过简洁的导入使用功能:
python复制from my_package.math import circle_area
22. 函数与调试技巧
22.1 使用pdb调试
Python内置调试器:
python复制import pdb
def buggy_function(x):
result = x * 2
pdb.set_trace() # 在这里暂停
return result + 5
进入调试模式后可以:
- n(ext)执行下一行
- c(ontinue)继续执行
- p(rint)查看变量
- l(ist)查看代码
22.2 断点函数
Python 3.7+可以直接用breakpoint():
python复制def complex_calculation(a, b):
breakpoint() # 相当于import pdb; pdb.set_trace()
# 复杂计算
这是我最常用的调试方式。
23. 函数与性能优化进阶
23.1 使用numba加速
对于数值计算密集型函数,numba可以显著提升速度:
python复制from numba import jit
@jit
def monte_carlo_pi(n):
count = 0
for _ in range(n):
x, y = random(), random()
if x*x + y*y <= 1:
count += 1
return 4 * count / n
在我的测试中,这个装饰器能让函数快100倍以上。
23.2 使用Cython编译
对于特别关键的代码,可以用Cython编译:
python复制# cython_example.pyx
def cython_sum(n):
cdef long total = 0
cdef int i
for i in range(n):
total += i
return total
编译后会生成C扩展模块,性能接近原生代码。
24. 函数与设计原则
24.1 单一职责原则
每个函数应该只做一件事。我曾经重构过一个"全能"函数:
python复制# 重构前
def process_data(data):
# 验证数据
# 清理数据
# 转换格式
# 保存到数据库
# 发送通知邮件
pass
# 重构后
def process_data(data):
validate_data(data)
cleaned = clean_data(data)
transformed = transform_data(cleaned)
save_to_db(transformed)
send_notification()
这样每个函数职责明确,更容易测试和维护。
24.2 DRY原则
Don't Repeat Yourself。发现重复代码时,应该提取为函数:
python复制# 重复代码
print("="*50)
print("报告开始")
print("="*50)
# 提取函数后
def print_header(title):
print("="*50)
print(title)
print("="*50)
print_header("报告开始")
这个简单的改变能让代码更易于维护。
25. 函数与代码审查
在团队协作中,函数是代码审查的重点。我通常会检查:
- 函数名是否准确描述功能
- 参数是否合理
- 是否有文档字符串
- 复杂度是否过高
- 是否有适当的错误处理
- 是否有单元测试
一个实用的技巧:让同事只看函数签名和文档字符串,看是否能理解函数用途。如果不能,就需要改进。
26. 函数与版本兼容性
当修改函数接口时,要考虑向后兼容:
python复制# 旧版本
def old_function(a, b):
pass
# 新版本
def new_function(a, b=None, c=None):
if b is not None:
# 旧调用方式
pass
else:
# 新调用方式
pass
或者更好的是,保留旧函数,添加新函数:
python复制def old_function(a, b):
return new_function(a, b=b)
def new_function(a, b=None, c=None):
# 新实现
pass
这样现有代码不会中断。
27. 函数与安全编程
编写安全函数需要注意:
- 验证所有输入
- 避免SQL注入
- 小心处理文件路径
- 限制资源使用
例如处理文件上传:
python复制def save_uploaded_file(upload, save_dir):
# 验证文件类型
allowed_types = ['image/jpeg', 'image/png']
if upload.content_type not in allowed_types:
raise ValueError("不允许的文件类型")
# 安全拼接路径
filename = secure_filename(upload.filename)
save_path = os.path.join(save_dir, filename)
# 检查路径是否在允许目录内
if not os.path.abspath(save_path).startswith(os.path.abspath(save_dir)):
raise ValueError("非法保存路径")
upload.save(save_path)
这些预防措施能避免很多安全问题。
28. 函数与性能监控
在生产环境中,我们需要监控函数性能:
python复制import time
from statsd import StatsClient
statsd = StatsClient()
def monitor_performance(func):
def wrapper(*args, **kwargs):
start = time.time()
try:
result = func(*args, **kwargs)
statsd.timing(f"function.{func.__name__}.success", (time.time()-start)*1000)
return result
except Exception:
statsd.timing(f"function.{func.__name__}.error", (time.time()-start)*1000)
raise
return wrapper
@monitor_performance
def critical_function():
pass
这样可以通过Grafana等工具可视化性能指标。
29. 函数与API设计
设计良好的API函数应该:
- 使用名词表示资源
- 使用动词表示操作
- 保持一致的命名风格
- 提供清晰的错误信息
例如RESTful风格的CRUD函数:
python复制def create_user(user_data):
pass
def get_user(user_id):
pass
def update_user(user_id, update_data):
pass
def delete_user(user_id):
pass
一致的命名让API更易于使用。
30. 函数与机器学习
在机器学习项目中,函数用于组织流程:
python复制def load_data(path):
pass
def preprocess(data):
pass
def train_model(X, y):
pass
def evaluate(model, X_test, y_test):
pass
def main():
data = load_data("dataset.csv")
X, y = preprocess(data)
model = train_model(X, y)
evaluate(model, X, y)
这种模块化设计方便实验不同算法。
31. 函数与并发模式
31.1 生产者-消费者模式
使用队列协调函数:
python复制from queue import Queue
from threading import Thread
def producer(q, items):
for item in items:
q.put(item)
def consumer(q):
while True:
item = q.get()
if item is None: # 终止信号
break
process(item)
q = Queue()
Thread(target=producer, args=(q, items)).start()
Thread(target=consumer, args=(q,)).start()
这种模式在处理流水线任务时非常有用。
31.2 线程池模式
使用concurrent.futures简化并发:
python复制from concurrent.futures import ThreadPoolExecutor
def process_item(item):
pass
with ThreadPoolExecutor(max_workers=4) as executor:
results = list(executor.map(process_item, items))
自动管理线程生命周期。
32. 函数与设计模式实现
32.1 观察者模式
用函数实现事件处理:
python复制class Event:
def __init__(self):
self.handlers = []
def register(self, handler):
self.handlers.append(handler)
def trigger(self, *args, **kwargs):
for handler in self.handlers:
handler(*args, **kwargs)
def log_event(message):
print(f"日志: {message}")
event = Event()
event.register(log_event)
event.trigger("系统启动")
这种模式在GUI和游戏开发中很常见。
32.2 状态模式
用函数表示状态:
python复制def state_idle():
print("空闲状态")
return state_working
def state_working():
print("工作状态")
return state_idle
state = state_idle
for _ in range(5):
state = state()
适合实现状态机逻辑。
33. 函数与算法实现
33.1 排序算法示例
实现快速排序:
python复制def quicksort(arr):
if len(arr) <= 1:
return arr
pivot = arr[len(arr) // 2]
left = [x for x in arr if x < pivot]
middle = [x for x in arr if x == pivot]
right = [x for x in arr if x > pivot]
return quicksort(left) + middle + quicksort(right)
函数式风格让算法实现更简洁。
33.2 搜索算法示例
二分查找实现:
python复制def binary_search(arr, target):
low, high = 0, len(arr) - 1
while low <= high:
mid = (low + high) // 2
if arr[mid] < target:
low = mid + 1
elif arr[mid] > target:
high = mid - 1
else:
return mid
return -1
注意处理边界条件。
34. 函数与数据结构操作
34.1 链表操作
实现链表反转:
python复制class Node:
def __init__(self, value):
self.value = value
self.next = None
def reverse_list(head):
prev = None
current = head
while current:
next_node = current.next
current.next = prev
prev = current
current = next_node
return prev
这种指针操作在面试中很常见。
34.2 树遍历
递归实现树的中序遍历:
python复制class TreeNode:
def __init__(self, value):
self.value = value
self.left = None
self.right = None
def inorder_traversal(root):
if root:
inorder_traversal(root.left)
print(root.value)
inorder_traversal(root.right)
递归让树操作代码非常简洁。
35. 函数与数学计算
35.1 数值积分
实现梯形法积分:
python复制def integrate(f, a, b, n=1000):
h = (b - a) / n
total = 0.5 * (f(a) + f(b))
for k in range(1, n):
total += f(a + k * h)
return total * h
可以计算任何函数的定积分:
python复制result = integrate(lambda x: x**2, 0, 1) # 应接近1/3
35.2 方程求根
实现牛顿迭代法:
python复制def newton_method(f, df, x0, tol=1e-6, max_iter=100):
x = x0
for _ in range(max_iter):
fx = f(x)
if abs(fx) < tol:
return x
dfx = df(x)
if dfx == 0:
break
x = x - fx / dfx
return None
需要提供函数及其导数。
36. 函数与文件处理
36.1 处理CSV文件
使用生成器处理大文件:
python复制import csv
def read_large_csv(file_path):
with open(file_path, 'r') as f:
reader = csv.DictReader(f)
for row in reader:
yield row
for record in read_large_csv("huge.csv"):
process(record)
这样不会一次性加载整个文件到内存。
36.2 处理JSON数据
安全的JSON解析:
python复制import json
def safe_json_parse(s):
try:
return json.loads(s)
except json.JSONDecodeError:
return None
包含错误处理更健壮。
37. 函数与网络编程
37.1 简单的HTTP服务器
使用http.server模块:
python复制from http.server import BaseHTTPRequestHandler, HTTPServer
class MyHandler(BaseHTTPRequestHandler):
def do_GET(self):
self.send_response(200)
self.send_header('Content-type', 'text/html')
self.end_headers()
self.wfile.write(b"Hello World")
def run_server(port=8000):
server = HTTPServer(('', port), MyHandler)
print(f"服务器运行在端口 {port}")
server.serve_forever()
适合快速原型开发。
37.2 发送HTTP请求
使用requests库:
python复制import requests
def fetch_url(url, retries=3):
for _ in range(retries):
try:
response = requests.get(url, timeout=5)
response.raise_for_status()
return response.text
except requests.RequestException:
continue
return None
包含重试逻辑更可靠。
38. 函数与数据库交互
38.1 使用SQLite
创建数据库连接函数:
python复制import sqlite3
from contextlib import contextmanager
@contextmanager
def get_db_connection(db_path):
conn = sqlite3.connect(db_path)
try:
yield conn
finally:
conn.close()
# 使用方式
with get_db_connection("mydb.db") as conn:
cursor = conn.cursor()
cursor.execute("SELECT * FROM users")
使用上下文管理器自动关闭连接。
38.2 ORM模式
使用SQLAlchemy:
python复制from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
name = Column(String)
def init_db(engine):
Base.metadata.create_all(engine)
这种模式让数据库操作更面向对象。
39. 函数与GUI开发
39.1 Tkinter示例
创建简单的GUI应用:
python复制import tkinter as tk
def create_window():
window = tk.Tk()
window.title("我的应用")
label = tk.Label(window, text="Hello World")
label.pack()
button = tk.Button(window, text="点击", command=on_click)
button.pack()
window.mainloop()
def on_click():
print("按钮被点击")
create_window()
事件处理通过函数实现。
39.2 PyQt示例
使用信号槽机制:
python复制from PyQt5.QtWidgets