1. 函数基础概念解析
函数是编程语言中最基础也最重要的概念之一。简单来说,函数就是一段可重复使用的代码块,它接收输入参数,执行特定操作,然后返回结果。就像数学中的函数y=f(x)一样,编程中的函数也有输入和输出。
在大多数编程语言中,函数通常由以下几个部分组成:
- 函数名:用来标识和调用函数的名称
- 参数列表:函数接收的输入值
- 函数体:包含实际执行的代码
- 返回值:函数执行后返回的结果
举个例子,在Python中定义一个简单的加法函数:
python复制def add_numbers(a, b):
"""将两个数字相加并返回结果"""
result = a + b
return result
这个函数名为add_numbers,接收两个参数a和b,在函数体内将它们相加,最后返回结果。我们可以这样调用它:
python复制sum = add_numbers(3, 5)
print(sum) # 输出8
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 为什么需要使用函数
2.1 代码复用性
函数最大的优势就是可以避免重复代码。假设我们需要在多处进行相同的计算,如果没有函数,我们就需要在每个地方都写一遍相同的代码。这不仅增加了工作量,也增加了出错的可能性。
2.2 提高可读性
良好的函数命名可以让代码更易读。比如calculate_average()比直接写计算平均值的代码更容易理解其意图。函数将复杂操作封装起来,让主程序逻辑更清晰。
2.3 便于维护
当需要修改某个功能时,如果这个功能被封装在函数中,我们只需要修改函数内部的实现,而不需要修改所有调用它的地方。这大大降低了维护成本。
2.4 模块化开发
函数允许我们将大问题分解为小问题,每个函数解决一个小问题,然后组合起来解决大问题。这种自顶向下的设计方法让复杂程序更易于开发和理解。
3. 函数的进阶特性
3.1 参数传递方式
不同语言中参数传递的方式可能不同。常见的有:
- 值传递:传递参数的副本,函数内修改不影响原值
- 引用传递:传递参数的引用,函数内修改会影响原值
- 默认参数:可以为参数指定默认值
- 可变参数:允许传入不定数量的参数
Python中的参数传递比较特殊,它既不是严格的值传递也不是引用传递,而是"对象引用传递"。对于不可变对象(如数字、字符串、元组),表现类似值传递;对于可变对象(如列表、字典),表现类似引用传递。
3.2 返回值处理
函数可以返回单个值,也可以返回多个值(在Python中是以元组形式返回)。有些语言还支持返回函数(高阶函数),这为函数式编程提供了可能。
3.3 作用域规则
函数内部定义的变量通常具有局部作用域,只在函数内有效。全局变量可以在函数内访问,但通常不建议过多使用全局变量,因为这会导致代码难以理解和维护。
3.4 递归函数
函数可以调用自身,这种技术称为递归。递归非常适合解决可以分解为相同子问题的问题,如阶乘计算、斐波那契数列、树遍历等。但需要注意设置递归终止条件,否则会导致无限递归。
4. 函数设计的最佳实践
4.1 单一职责原则
一个好的函数应该只做一件事,并且做好这件事。如果一个函数做了太多事情,就应该考虑将其拆分为多个更小的函数。这会让代码更易于理解、测试和维护。
4.2 合理的命名
函数名应该清晰表达其功能,通常使用动词+名词的形式,如calculate_total()、get_user_info()等。避免使用过于笼统的名称如process_data(),除非函数确实处理非常通用的操作。
4.3 适当的长度
一般来说,函数不应该太长。如果函数超过一屏(约20-30行),就可能需要考虑是否违反了单一职责原则。当然,这也不是绝对的,有时较长的函数也是合理的,特别是当逻辑确实需要这么多代码时。
4.4 文档字符串
为函数添加清晰的文档字符串(docstring)是一个好习惯。文档字符串应该说明函数的功能、参数、返回值和可能的异常。在Python中,文档字符串通常放在函数定义后的第一行,用三引号包围。
4.5 错误处理
函数应该妥善处理可能出现的错误情况。可以通过返回值、异常或其他机制来报告错误。重要的是让调用者知道函数执行是否成功,以及失败的原因。
5. 函数式编程概念
5.1 纯函数
纯函数是指没有副作用(不修改外部状态)并且输出只依赖于输入的函数。给定相同的输入,纯函数总是返回相同的输出。纯函数更容易测试和推理。
5.2 高阶函数
高阶函数是指可以接收函数作为参数或返回函数作为结果的函数。常见的高阶函数包括map、filter和reduce等。
5.3 匿名函数
匿名函数(也称为lambda函数)是没有名称的小型函数。它们通常用于需要简单函数作为参数的场合。例如在Python中:
python复制numbers = [1, 2, 3, 4]
squared = list(map(lambda x: x**2, numbers))
5.4 闭包
闭包是指能够记住并访问其词法作用域的函数,即使该函数在其词法作用域之外执行。闭包可以用来创建有状态的函数。
6. 实际应用案例
6.1 数据处理函数
假设我们需要处理一组学生成绩数据,可以创建以下函数:
python复制def calculate_average(scores):
"""计算平均分"""
return sum(scores) / len(scores)
def find_max(scores):
"""找出最高分"""
return max(scores)
def grade_student(score):
"""根据分数给出等级"""
if score >= 90:
return 'A'
elif score >= 80:
return 'B'
elif score >= 70:
return 'C'
elif score >= 60:
return 'D'
else:
return 'F'
6.2 文件处理函数
处理文件时,函数可以大大简化代码:
python复制def read_file(filename):
"""读取文件内容"""
try:
with open(filename, 'r') as file:
return file.read()
except IOError as e:
print(f"无法读取文件: {e}")
return None
def write_file(filename, content):
"""写入内容到文件"""
try:
with open(filename, 'w') as file:
file.write(content)
return True
except IOError as e:
print(f"无法写入文件: {e}")
return False
6.3 数学计算函数
对于复杂的数学计算,函数可以让代码更清晰:
python复制def quadratic_formula(a, b, c):
"""解二次方程ax² + bx + c = 0"""
discriminant = b**2 - 4*a*c
if discriminant < 0:
return None # 无实数解
sqrt_discriminant = discriminant**0.5
x1 = (-b + sqrt_discriminant) / (2*a)
x2 = (-b - sqrt_discriminant) / (2*a)
return x1, x2
7. 调试与测试函数
7.1 单元测试
为函数编写单元测试是确保其正确性的好方法。Python中可以使用unittest模块:
python复制import unittest
class TestMathFunctions(unittest.TestCase):
def test_add_numbers(self):
self.assertEqual(add_numbers(2, 3), 5)
self.assertEqual(add_numbers(-1, 1), 0)
self.assertEqual(add_numbers(0, 0), 0)
def test_quadratic_formula(self):
self.assertEqual(quadratic_formula(1, -3, 2), (2.0, 1.0))
self.assertIsNone(quadratic_formula(1, 0, 1))
if __name__ == '__main__':
unittest.main()
7.2 调试技巧
调试函数时,可以:
- 使用print语句输出中间结果
- 使用断点调试器逐步执行
- 检查输入参数是否符合预期
- 验证返回值是否正确
- 考虑边界条件和异常情况
7.3 性能分析
对于性能关键的函数,可以使用分析工具(如Python的cProfile)来找出瓶颈:
python复制import cProfile
def slow_function():
# 一些耗时操作
pass
cProfile.run('slow_function()')
8. 函数在不同语言中的实现
8.1 Python中的函数
Python函数非常灵活,支持:
- 位置参数和关键字参数
- 默认参数值
- 可变参数列表(*args和**kwargs)
- 类型提示(Python 3.5+)
- 嵌套函数和闭包
- 装饰器
8.2 JavaScript中的函数
JavaScript函数是一等公民,可以:
- 作为变量赋值
- 作为参数传递
- 作为返回值
- 使用箭头函数简化语法
- 具有函数作用域(ES5)或块作用域(ES6 let/const)
8.3 Java中的方法
Java中函数称为方法,特点是:
- 必须属于某个类
- 需要明确指定返回类型(void表示无返回值)
- 参数和返回值都有严格的类型检查
- 支持方法重载(同名不同参)
8.4 C语言中的函数
C语言函数特点包括:
- 需要先声明后使用
- 参数传递是值传递
- 可以返回指针
- 支持函数指针
- 没有默认参数和函数重载
9. 函数设计模式
9.1 工厂函数
工厂函数是创建并返回对象的函数。它可以封装对象创建的复杂性,并提供灵活的创建方式。
python复制def create_person(name, age, job=None):
"""创建一个人物字典"""
person = {
'name': name,
'age': age,
'job': job
}
return person
9.2 回调函数
回调函数是作为参数传递给其他函数的函数,通常用于异步操作或事件处理。
python复制def process_data(data, callback):
"""处理数据并调用回调函数"""
result = data * 2 # 一些处理
callback(result)
def print_result(result):
"""打印结果的回调函数"""
print(f"结果是: {result}")
process_data(10, print_result) # 输出"结果是: 20"
9.3 装饰器模式
装饰器是在不修改原函数代码的情况下扩展函数功能的高阶函数。Python有专门的装饰器语法:
python复制def log_time(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
@log_time
def slow_function():
time.sleep(1)
slow_function() # 输出"slow_function 执行时间: 1.0001秒"
10. 函数优化技巧
10.1 记忆化(Memoization)
对于计算密集型且可能被重复调用的函数,可以使用记忆化技术缓存结果:
python复制from functools import lru_cache
@lru_cache(maxsize=None)
def fibonacci(n):
if n < 2:
return n
return fibonacci(n-1) + fibonacci(n-2)
10.2 向量化操作
对于数值计算,使用向量化操作(如NumPy)比循环更高效:
python复制import numpy as np
# 低效的实现
def sum_squares(numbers):
total = 0
for n in numbers:
total += n**2
return total
# 高效的向量化实现
def sum_squares_vec(numbers):
return np.sum(np.array(numbers)**2)
10.3 并行处理
对于可以并行处理的任务,可以使用多进程或多线程:
python复制from multiprocessing import Pool
def process_item(item):
# 处理单个项目
return item * 2
def process_all(items):
with Pool() as pool:
results = pool.map(process_item, items)
return results
10.4 惰性求值
对于可能不需要全部结果的情况,可以使用生成器实现惰性求值:
python复制def generate_numbers(n):
"""生成前n个数字"""
i = 0
while i < n:
yield i
i += 1
# 使用时不会一次性生成所有数字,而是按需生成
for num in generate_numbers(1000000):
if num > 10:
break
print(num)
11. 常见错误与陷阱
11.1 可变默认参数
在Python中,默认参数在函数定义时求值一次,而不是每次调用时:
python复制# 错误的方式
def add_item(item, items=[]):
items.append(item)
return items
# 正确的方式
def add_item(item, items=None):
if items is None:
items = []
items.append(item)
return items
11.2 修改全局变量
在函数内修改全局变量需要使用global关键字,否则会创建局部变量:
python复制count = 0
def increment():
global count
count += 1
11.3 返回局部变量的引用
在函数内创建的可变对象(如列表)并返回时要注意,外部修改会影响原对象:
python复制def get_list():
return [1, 2, 3]
my_list = get_list()
my_list.append(4) # 这会修改返回的列表
11.4 递归深度限制
递归函数可能达到最大递归深度(Python默认约1000),导致栈溢出。对于深度递归问题,可以考虑使用迭代或尾递归优化。
12. 函数在项目中的应用
12.1 模块化设计
在大型项目中,函数应该按照功能组织到不同的模块中。例如:
database.py:包含所有数据库操作函数utils.py:包含各种工具函数models.py:包含数据处理函数views.py:包含用户界面相关函数
12.2 API设计
设计良好的函数接口是创建清晰API的关键。考虑:
- 函数命名是否清晰表达意图
- 参数是否合理且必要
- 返回值是否明确且一致
- 错误处理是否完善
12.3 测试驱动开发
可以先编写测试用例,再实现函数,确保函数从一开始就满足需求:
python复制# 先写测试
def test_calculate_discount():
assert calculate_discount(100, 10) == 90
assert calculate_discount(50, 100) == 0
assert calculate_discount(0, 10) == 0
# 再实现函数
def calculate_discount(price, discount):
"""计算折扣后的价格"""
discounted = price - discount
return max(discounted, 0)
12.4 代码审查要点
审查函数时关注:
- 是否遵循单一职责原则
- 命名是否清晰准确
- 是否有适当的文档和注释
- 错误处理是否完善
- 是否有性能问题
- 是否考虑了边界条件
13. 函数与面向对象编程
13.1 方法与函数的区别
在面向对象编程中,方法是与对象关联的函数。主要区别在于:
- 方法隐式接收对象实例作为第一个参数(在Python中是self)
- 方法可以访问和修改对象的状态
- 方法通常表示对象的行为
13.2 静态方法与类方法
Python中还有两种特殊的方法:
- 静态方法:使用
@staticmethod装饰,不接收隐式的self或cls参数 - 类方法:使用
@classmethod装饰,接收类作为第一个参数(cls)
python复制class MyClass:
@staticmethod
def static_method():
print("这是一个静态方法")
@classmethod
def class_method(cls):
print(f"这是一个类方法,类名是{cls.__name__}")
13.3 函数式与面向对象的结合
现代编程往往结合函数式和面向对象的优点。例如:
- 在类中使用纯方法(不修改实例状态)
- 将高阶函数作为方法
- 使用lambda表达式简化代码
14. 函数在算法中的应用
14.1 排序算法
大多数排序算法都可以用函数实现:
python复制def bubble_sort(arr):
n = len(arr)
for i in range(n):
for j in range(0, n-i-1):
if arr[j] > arr[j+1]:
arr[j], arr[j+1] = arr[j+1], arr[j]
return arr
14.2 搜索算法
搜索算法也常封装为函数:
python复制def binary_search(arr, target):
low = 0
high = len(arr) - 1
while low <= high:
mid = (low + high) // 2
if arr[mid] == target:
return mid
elif arr[mid] < target:
low = mid + 1
else:
high = mid - 1
return -1
14.3 递归算法
许多经典算法使用递归实现:
python复制def factorial(n):
if n == 0:
return 1
return n * factorial(n-1)
14.4 动态规划
动态规划问题通常用函数+记忆化解决:
python复制def fib(n, memo={}):
if n in memo:
return memo[n]
if n <= 2:
return 1
memo[n] = fib(n-1, memo) + fib(n-2, memo)
return memo[n]
15. 函数在数据处理中的应用
15.1 数据清洗
创建专门的数据清洗函数:
python复制def clean_string(s):
"""清洗字符串:去除空格,转换为小写"""
return s.strip().lower()
def remove_outliers(data, threshold=3):
"""移除超出阈值标准差的数据点"""
mean = np.mean(data)
std = np.std(data)
return [x for x in data if abs(x - mean) < threshold * std]
15.2 数据转换
使用函数进行数据格式转换:
python复制def convert_date(date_str, format_in, format_out):
"""转换日期格式"""
dt = datetime.strptime(date_str, format_in)
return dt.strftime(format_out)
15.3 特征工程
创建特征提取函数:
python复制def extract_features(text):
"""从文本中提取特征"""
features = {
'length': len(text),
'word_count': len(text.split()),
'has_digit': any(c.isdigit() for c in text),
'has_upper': any(c.isupper() for c in text)
}
return features
15.4 数据聚合
编写数据聚合函数:
python复制def aggregate_data(data, group_by, agg_func):
"""按指定字段分组并应用聚合函数"""
grouped = {}
for item in data:
key = item[group_by]
if key not in grouped:
grouped[key] = []
grouped[key].append(item)
return {k: agg_func(v) for k, v in grouped.items()}
16. 函数在Web开发中的应用
16.1 路由处理函数
在Web框架中,路由通常映射到处理函数:
python复制@app.route('/user/<username>')
def show_user_profile(username):
return f'用户 {username}'
16.2 中间件函数
中间件函数处理请求和响应:
python复制def log_middleware(next):
def middleware(request):
print(f"收到请求: {request.path}")
response = next(request)
print(f"返回响应: {response.status}")
return response
return middleware
16.3 模板辅助函数
创建模板中使用的辅助函数:
python复制def format_price(amount):
"""格式化价格为货币形式"""
return f"${amount:,.2f}"
# 在模板中使用
# {{ format_price(product.price) }}
16.4 API端点函数
REST API端点通常对应函数:
python复制@app.route('/api/products', methods=['GET'])
def get_products():
products = db.get_all_products()
return jsonify([p.to_dict() for p in products])
17. 函数在GUI开发中的应用
17.1 事件处理函数
GUI应用中,用户操作触发事件处理函数:
python复制def on_button_click():
print("按钮被点击了")
button = Button(text="点击我", command=on_button_click)
17.2 数据绑定函数
创建数据与UI元素绑定的函数:
python复制def update_label(text_var, entry_widget):
"""将输入框内容更新到标签"""
text_var.set(entry_widget.get())
17.3 自定义绘图函数
实现自定义绘图逻辑:
python复制def draw_pie_chart(canvas, data):
"""在画布上绘制饼图"""
total = sum(data.values())
start_angle = 0
for label, value in data.items():
angle = 360 * value / total
canvas.create_arc(10, 10, 200, 200,
start=start_angle, extent=angle,
fill=random_color())
start_angle += angle
17.4 布局辅助函数
简化复杂布局的创建:
python复制def create_labeled_entry(parent, text):
"""创建带标签的输入框"""
frame = Frame(parent)
Label(frame, text=text).pack(side=LEFT)
entry = Entry(frame)
entry.pack(side=LEFT)
return frame, entry
18. 函数在游戏开发中的应用
18.1 游戏逻辑函数
实现游戏核心逻辑:
python复制def check_collision(obj1, obj2):
"""检测两个游戏对象是否碰撞"""
return (obj1.x < obj2.x + obj2.width and
obj1.x + obj1.width > obj2.x and
obj1.y < obj2.y + obj2.height and
obj1.y + obj1.height > obj2.y)
18.2 AI行为函数
控制游戏AI行为:
python复制def decide_ai_move(ai, player):
"""决定AI的下一步移动"""
distance = ((ai.x - player.x)**2 + (ai.y - player.y)**2)**0.5
if distance < 100: # 如果玩家靠近,逃跑
return move_away_from(ai, player)
else: # 否则随机移动
return random_direction()
18.3 物理模拟函数
实现简单物理效果:
python复制def apply_gravity(objects, gravity=9.8, dt=0.1):
"""对所有对象应用重力"""
for obj in objects:
if not obj.is_static:
obj.velocity_y += gravity * dt
obj.y += obj.velocity_y * dt
18.4 状态更新函数
处理游戏状态更新:
python复制def update_game_state(state):
"""更新整个游戏状态"""
update_players(state['players'])
update_enemies(state['enemies'])
update_projectiles(state['projectiles'])
check_collisions(state)
update_score(state)
19. 函数在自动化脚本中的应用
19.1 文件批量处理
编写批量处理文件的函数:
python复制def batch_rename(files, pattern):
"""批量重命名文件"""
for i, filepath in enumerate(files):
dirname, filename = os.path.split(filepath)
ext = os.path.splitext(filename)[1]
new_name = pattern.format(i+1) + ext
os.rename(filepath, os.path.join(dirname, new_name))
19.2 网页自动化
实现网页自动化操作:
python复制def scrape_website(url, selector):
"""抓取网页中特定选择器的内容"""
driver = webdriver.Chrome()
driver.get(url)
elements = driver.find_elements_by_css_selector(selector)
results = [e.text for e in elements]
driver.quit()
return results
19.3 系统监控
创建系统监控函数:
python复制def monitor_disk_usage(threshold=90):
"""监控磁盘使用率,超过阈值报警"""
usage = psutil.disk_usage('/').percent
if usage > threshold:
send_alert(f"磁盘使用率过高: {usage}%")
19.4 定时任务
实现定时执行的功能:
python复制def run_periodically(func, interval):
"""定期执行函数"""
while True:
func()
time.sleep(interval)
20. 函数式编程实践
20.1 使用map/filter/reduce
这些高阶函数可以替代许多循环:
python复制numbers = [1, 2, 3, 4, 5]
# 使用map应用函数
squares = list(map(lambda x: x**2, numbers))
# 使用filter过滤元素
evens = list(filter(lambda x: x % 2 == 0, numbers))
# 使用reduce进行累积计算
from functools import reduce
product = reduce(lambda x, y: x * y, numbers)
20.2 函数组合
将多个函数组合成一个新函数:
python复制def compose(*funcs):
"""组合多个函数"""
def composed(x):
for f in reversed(funcs):
x = f(x)
return x
return composed
# 使用示例
add1 = lambda x: x + 1
mul2 = lambda x: x * 2
composed = compose(add1, mul2)
print(composed(3)) # (3 * 2) + 1 = 7
20.3 柯里化
将多参数函数转换为一系列单参数函数:
python复制def curry(func):
"""柯里化装饰器"""
def curried(*args):
if len(args) >= func.__code__.co_argcount:
return func(*args)
return lambda *more: curried(*(args + more))
return curried
@curry
def add_three(a, b, c):
return a + b + c
add1 = add_three(1)
add1and2 = add1(2)
result = add1and2(3) # 6
20.4 不可变数据结构
在函数式编程中,倾向于使用不可变数据:
python复制def update_dict(d, key, value):
"""创建新字典而不是修改原字典"""
return {**d, key: value}
21. 异步函数编程
21.1 协程与async/await
Python中使用async/await定义异步函数:
python复制async def fetch_data(url):
"""异步获取数据"""
async with aiohttp.ClientSession() as session:
async with session.get(url) as response:
return await response.json()
21.2 事件循环
运行异步函数需要事件循环:
python复制async def main():
data = await fetch_data('https://api.example.com/data')
print(data)
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
21.3 并发任务
同时运行多个异步任务:
python复制async def download_all(urls):
"""并发下载多个URL"""
tasks = [fetch_data(url) for url in urls]
return await asyncio.gather(*tasks)
21.4 异步生成器
使用异步生成器处理流数据:
python复制async def async_counter(n):
"""异步计数器"""
for i in range(n):
yield i
await asyncio.sleep(1)
async def main():
async for num in async_counter(5):
print(num)
22. 函数测试与调试进阶
22.1 模拟与打桩
使用unittest.mock模拟函数依赖:
python复制from unittest.mock import patch
def get_data():
# 实际会访问外部服务的函数
pass
@patch('__main__.get_data')
def test_processing(mock_get_data):
mock_get_data.return_value = [1, 2, 3]
result = process_data()
assert result == 6
22.2 性能剖析
使用cProfile分析函数性能:
python复制import cProfile
def slow_function():
# 一些耗时操作
pass
profiler = cProfile.Profile()
profiler.runcall(slow_function)
profiler.print_stats()
22.3 代码覆盖率
检查测试对函数的覆盖情况:
python复制# 使用pytest-cov插件
# pytest --cov=my_module tests/
22.4 调试技巧
高级调试技巧:
- 使用pdb设置断点
- 检查函数调用栈
- 记录函数执行日志
- 可视化函数调用关系
23. 函数与设计模式
23.1 策略模式
使用函数实现策略模式:
python复制def strategy_add(a, b):
return a + b
def strategy_multiply(a, b):
return a * b
class Calculator:
def __init__(self, strategy):
self.strategy = strategy
def execute(self, a, b):
return self.strategy(a, b)
calc = Calculator(strategy_add)
print(calc.execute(3, 4)) # 7
23.2 观察者模式
用函数实现观察者回调:
python复制class Observable:
def __init__(self):
self._observers = []
def add_observer(self, observer):
self._observers.append(observer)
def notify(self, *args):
for observer in self._observers:
observer(*args)
def logger(message):
print(f"日志: {message}")
subject = Observable()
subject.add_observer(logger)
subject.notify("事件发生了")
23.3 命令模式
将操作封装为函数对象:
python复制class Command:
def __init__(self, execute):
self.execute = execute
def __call__(self):
return self.execute()
def save_action():
print("保存文件")
save_command = Command(save_action)
save_command() # 执行命令
23.4 模板方法
使用高阶函数实现模板:
python复制def template_method(step1, step2):
"""模板方法框架"""
print("开始执行")
step1()
step2()
print("执行结束")
def custom_implementation():
template_method(
lambda: print("自定义步骤1"),
lambda: print("自定义步骤2")
)
24. 函数元编程
24.1 动态创建函数
在运行时创建函数:
python复制def create_adder(n):
"""创建添加n的函数"""
def adder(x):
return x + n
return adder
add5 = create_adder(5)
print(add5(3)) # 8
24.2 函数自省
检查函数属性:
python复制def example(a, b=1):
"""示例函数"""
return a + b
print(example.__name__) # 'example'
print(example.__doc__) # '示例函数'
print(example.__code__.co_varnames) # ('a', 'b')
24.3 装饰器工厂
创建参数化装饰器:
python复制def repeat(n):
"""执行函数n次的装饰器工厂"""
def decorator(func):
def wrapper(*args, **kwargs):
for _ in range(n):
result = func(*args, **kwargs)
return result
return wrapper
return decorator
@repeat(3)
def say_hello():
print("Hello")
say_hello() # 打印3次Hello
24.4 修改函数行为
动态修改函数:
python复制def original():
return 42
def wrapper():
print("调用前")
result = original()
print("调用后")
return result
original = wrapper
original() # 现在会打印调用前后信息
25. 函数最佳实践总结
25.1 保持函数短小精悍
理想情况下,函数应该短到只做一件事。如果函数太长,考虑是否可以将部分逻辑提取到辅助函数中。
25.2 有意义的命名
函数名应该清晰表达其功能,使用动词开头,如calculate_total()、get_user_info()等。避免模糊的名称如process_data()。
25.3 单一抽象层级
函数中的所有语句应该在同一个抽象层级上。不要混入高层业务逻辑和底层实现细节。
25.4 最少参数原则
尽量减少函数参数数量。如果有太多参数,考虑是否可以将相关参数组合成对象。
25.5 无副作用
理想情况下,函数应该只通过返回值与外界通信,避免修改全局状态或输入参数。
25.6 防御性编程
检查输入参数的有效性,处理可能的错误情况,提供清晰的错误信息。
25.7 完善的文档
为公共函数编写清晰的文档字符串,说明功能、参数、返回值和可能的异常。
25.8 单元测试
为重要函数编写单元测试,覆盖各种正常和异常情况。测试应该独立于函数实现。
25.9 性能考量
对于性能关键的函数,进行必要的优化,但要避免过早优化。先保证正确性,再考虑性能。
25.10 重构迭代
随着需求变化,定期重构函数,保持代码清晰。不要害怕修改现有函数以适应新需求。
