1. Python函数精练12题:从入门到精通的实战指南
作为Python最基础也最重要的组成部分,函数是每位开发者必须掌握的技能。这12道精心设计的题目覆盖了函数定义、参数传递、作用域、闭包、装饰器等核心知识点,特别适合已经学完基础语法但缺乏实战经验的开发者。我在教学过程中发现,很多初学者看懂了函数概念却不会灵活运用,这套练习题正是为了解决这个痛点而设计的。
2. 函数基础与参数传递
2.1 函数定义与调用
Python使用def关键字定义函数,函数名应使用小写字母和下划线的组合。一个规范的函数定义应该包含文档字符串(docstring),这是Python特有的文档规范。
python复制def calculate_area(radius):
"""计算圆的面积
参数:
radius (float): 圆的半径
返回:
float: 圆的面积
"""
return 3.14159 * radius ** 2
注意:函数定义时缩进必须一致,通常使用4个空格。混合使用空格和制表符会导致IndentationError。
2.2 参数传递机制
Python的参数传递是"对象引用传递",对于可变对象(如列表、字典)和不可变对象(如数字、字符串)表现不同:
python复制def modify_list(lst):
lst.append(4) # 会修改原始列表
lst = [7,8,9] # 不会影响原始列表
my_list = [1,2,3]
modify_list(my_list)
print(my_list) # 输出: [1,2,3,4]
3. 函数进阶特性
3.1 默认参数与可变参数
默认参数必须指向不可变对象,否则可能产生意外行为:
python复制# 错误示范
def add_item(item, items=[]):
items.append(item)
return items
print(add_item(1)) # [1]
print(add_item(2)) # [1,2] 不是预期的[2]
# 正确写法
def add_item(item, items=None):
if items is None:
items = []
items.append(item)
return items
可变参数(*args和**kwargs)让函数更灵活:
python复制def logger(func):
def wrapper(*args, **kwargs):
print(f"调用{func.__name__},参数: {args}, {kwargs}")
return func(*args, **kwargs)
return wrapper
3.2 闭包与装饰器
闭包是指内部函数引用了外部函数的变量:
python复制def make_multiplier(factor):
def multiplier(x):
return x * factor
return multiplier
double = make_multiplier(2)
print(double(5)) # 输出10
装饰器是Python的重要特性,常用于日志、计时、权限检查等:
python复制import time
def timing_decorator(func):
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
4. 12道精选题解析
4.1 基础题组
- 编写一个函数,接受两个数字参数,返回它们的和与差的元组
- 实现一个计算阶乘的递归函数
- 编写函数检查字符串是否是回文
python复制# 第3题解答
def is_palindrome(s):
s = ''.join(filter(str.isalnum, s)).lower()
return s == s[::-1]
4.2 中级题组
- 实现map函数的简化版my_map
- 编写生成斐波那契数列的生成器函数
- 实现一个记忆化装饰器,缓存函数结果
python复制# 第6题解答
def memoize(func):
cache = {}
def wrapper(*args):
if args not in cache:
cache[args] = func(*args)
return cache[args]
return wrapper
4.3 高级题组
- 实现参数类型检查装饰器
- 编写支持链式调用的类装饰器
- 创建上下文管理器装饰器
python复制# 第9题解答
from contextlib import ContextDecorator
class log_time(ContextDecorator):
def __enter__(self):
self.start = time.time()
return self
def __exit__(self, *exc):
print(f"耗时: {time.time()-self.start:.4f}秒")
return False
4.4 综合应用题
- 实现简单的路由装饰器
- 构建管道式数据处理函数
- 设计带状态保存的装饰器
python复制# 第12题解答
def stateful_decorator(func):
func.call_count = 0
def wrapper(*args, **kwargs):
func.call_count += 1
print(f"这是第{func.call_count}次调用")
return func(*args, **kwargs)
return wrapper
5. 常见问题与调试技巧
5.1 作用域问题
新手常遇到UnboundLocalError,通常是因为在函数内修改了全局变量:
python复制count = 0
def increment():
global count # 必须声明global
count += 1
5.2 装饰器陷阱
装饰器会改变函数的元信息,使用functools.wraps可以保留原始信息:
python复制from functools import wraps
def my_decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
return func(*args, **kwargs)
return wrapper
5.3 性能优化
对于递归函数,记忆化可以大幅提升性能。以斐波那契数列为例:
python复制@memoize
def fib(n):
if n < 2:
return n
return fib(n-1) + fib(n-2)
6. 实战建议与扩展学习
在实际项目中,函数应该保持单一职责原则,每个函数只做一件事。我建议:
- 函数长度控制在50行以内
- 参数不超过5个,过多考虑使用对象封装
- 为公共函数编写完整的文档字符串
- 使用类型注解提高代码可读性
python复制from typing import List, Tuple
def process_data(data: List[str]) -> Tuple[int, float]:
"""处理字符串数据
参数:
data: 字符串列表
返回:
包含处理结果数量和平均值的元组
"""
count = len(data)
avg = sum(len(s) for s in data) / count
return count, avg
掌握函数式编程技巧能让代码更简洁:
python复制from functools import partial
# 创建固定参数的函数版本
pow_of_2 = partial(pow, exp=2)
print(pow_of_2(5)) # 25
