Python3 函数详解
函数是 Python 编程中最基本的代码组织单元,它将重复的操作封装为可复用的模块,提高代码的可读性和维护性。本文将从基础到高级,全面解析 Python3 函数的核心概念、语法特性及最佳实践。
一、函数的基本定义与调用
1. 函数的定义语法
def function_name(parameters):
"""函数文档字符串"""
# 函数体
return [expression] # 可选返回值
- 参数说明:
def:定义函数的关键字function_name:函数名,遵循标识符命名规则parameters:参数列表,多个参数用逗号分隔return:返回语句,可省略(默认返回None)
示例:
def add(a, b):
"""计算两个数的和"""
return a + b
result = add(3, 5) # 调用函数,返回8
2. 参数传递方式
Python 函数参数传递分为位置参数和关键字参数:
def person_info(name, age, city="Beijing"):
"""打印个人信息"""
print(f"{name}, {age}岁, 城市: {city}")
# 位置参数调用
person_info("张三", 25) # 输出: 张三, 25岁, 城市: Beijing
# 关键字参数调用
person_info(age=30, name="李四", city="Shanghai") # 输出: 李四, 30岁, 城市: Shanghai
# 默认参数
person_info("王五", 22, "Guangzhou") # 输出: 王五, 22岁, 城市: Guangzhou
注意事项:
- 关键字参数必须在位置参数之后
- 默认参数必须放在参数列表末尾
- 避免使用可变对象作为默认参数(如空列表
[])
二、函数参数的高级特性
1. 可变参数(*args 与 **kwargs)
*args:接收任意数量的位置参数,打包为元组**kwargs:接收任意数量的关键字参数,打包为字典
def sum_all(*args, **kwargs):
"""计算所有数字的和,可通过scale参数指定缩放因子"""
total = sum(args)
scale = kwargs.get("scale", 1)
return total * scale
result1 = sum_all(1, 2, 3) # 6 * 1 = 6
result2 = sum_all(1, 2, 3, scale=2) # 6 * 2 = 12
result3 = sum_all(1, 2, 3, factor=0.5) # 6 * 1 = 6(忽略未定义参数)
典型应用场景:
- 装饰器开发
- 函数参数透传
- 实现灵活的配置接口
2. 参数解包(Unpacking)
使用
*和**将可迭代对象或字典解包为函数参数:def add(a, b, c):
return a + b + c
# 列表/元组解包
args = [1, 2, 3]
result = add(*args) # 等价于 add(1, 2, 3)
# 字典解包
kwargs = {"a": 1, "b": 2, "c": 3}
result = add(**kwargs) # 等价于 add(a=1, b=2, c=3)
3. 强制关键字参数(Python 3.8+)
使用
*作为分隔符,其后的参数必须通过关键字传递:def calculate(a, b, *, scale=1, offset=0):
"""强制scale和offset必须通过关键字传递"""
return (a + b) * scale + offset
result = calculate(1, 2, scale=2, offset=1) # 正确
result = calculate(1, 2, 2, 1) # 错误:scale和offset必须是关键字参数
三、函数的返回值与多返回值
1. 单返回值
def get_full_name(first, last):
return f"{first} {last}"
name = get_full_name("John", "Doe") # 返回 "John Doe"
2. 多返回值(元组 / 列表 / 字典)
def get_user_info():
"""返回用户信息(元组)"""
return "张三", 25, "Beijing"
name, age, city = get_user_info() # 元组解包
def get_config():
"""返回配置字典"""
return {"host": "localhost", "port": 8080}
config = get_config()
print(config["host"]) # 输出: localhost
3. 生成器函数(返回迭代器)
使用
yield关键字创建生成器函数:def fibonacci(n):
"""生成斐波那契数列"""
a, b = 0, 1
for _ in range(n):
yield a
a, b = b, a + b
# 使用生成器
for num in fibonacci(5):
print(num) # 输出: 0 1 1 2 3
四、函数的作用域与闭包
1. 作用域规则(LEGB 原则)
Python 按以下顺序查找变量:
- Local:函数内部
- Enclosing:嵌套函数的外部函数
- Global:全局作用域
- Built-in:内置模块
x = 10 # 全局变量
def outer():
x = 20 # 闭包变量
def inner():
x = 30 # 局部变量
print(x) # 输出: 30
inner()
outer()
2. 闭包(Closure)
闭包是引用了外部函数变量的内部函数,即使外部函数已执行完毕:
def multiplier(factor):
def multiply_by_factor(num):
return num * factor # 引用外部变量factor
return multiply_by_factor # 返回闭包
double = multiplier(2)
triple = multiplier(3)
print(double(5)) # 输出: 10
print(triple(5)) # 输出: 15
闭包的应用场景:
- 装饰器实现
- 延迟计算
- 实现私有变量
五、装饰器:函数的元编程
1. 基本装饰器
装饰器是一个接收函数并返回新函数的高阶函数:
def timer_decorator(func):
def wrapper(*args, **kwargs):
start_time = time.time()
result = func(*args, **kwargs)
end_time = time.time()
print(f"{func.__name__} 执行耗时: {end_time - start_time}秒")
return result
return wrapper
@timer_decorator
def heavy_computation(n):
return sum(i*i for i in range(n))
heavy_computation(1000000) # 自动应用装饰器
2. 带参数的装饰器
通过嵌套函数实现装饰器参数:
def repeat(n):
def decorator(func):
def wrapper(*args, **kwargs):
result = None
for _ in range(n):
result = func(*args, **kwargs)
return result
return wrapper
return decorator
@repeat(3)
def say_hello():
print("Hello!")
say_hello() # 输出三次Hello!
3. 类装饰器
使用类实现装饰器:
class CountCalls:
def __init__(self, func):
self.func = func
self.count = 0
def __call__(self, *args, **kwargs):
self.count += 1
print(f"第{self.count}次调用 {self.func.__name__}")
return self.func(*args, **kwargs)
@CountCalls
def greet(name):
print(f"Hello, {name}!")
greet("Alice") # 输出: 第1次调用 greet\nHello, Alice!
greet("Bob") # 输出: 第2次调用 greet\nHello, Bob!
六、函数式编程特性
1. 高阶函数
接收函数作为参数或返回函数的函数:
def apply_operation(operation, a, b):
return operation(a, b)
result = apply_operation(lambda x, y: x + y, 3, 5) # 传递匿名函数
print(result) # 输出: 8
2. 匿名函数(lambda)
用于创建简单的单行函数:
# 标准函数
def add(a, b):
return a + b
# 等价的lambda函数
add = lambda a, b: a + b
# 常见应用:排序
students = [("Alice", 25), ("Bob", 20), ("Charlie", 22)]
students.sort(key=lambda x: x[1]) # 按年龄排序
print(students) # 输出: [("Bob", 20), ("Charlie", 22), ("Alice", 25)]
3. 内置高阶函数
map():对可迭代对象的每个元素应用函数filter():过滤可迭代对象中的元素reduce():累积计算可迭代对象的元素
# map示例
numbers = [1, 2, 3, 4]
squared = list(map(lambda x: x**2, numbers)) # [1, 4, 9, 16]
# filter示例
even_numbers = list(filter(lambda x: x % 2 == 0, numbers)) # [2, 4]
# reduce示例(需导入)
from functools import reduce
product = reduce(lambda x, y: x * y, numbers) # 1*2*3*4 = 24
七、函数的文档与类型注解
1. 文档字符串(Docstring)
def calculate_average(numbers):
"""
计算数字列表的平均值
参数:
numbers (list): 包含数字的列表
返回:
float: 平均值
异常:
ValueError: 当列表为空时抛出
"""
if not numbers:
raise ValueError("列表不能为空")
return sum(numbers) / len(numbers)
通过
__doc__属性访问文档字符串:print(calculate_average.__doc__)
2. 类型注解(Python 3.5+)
def greeting(name: str) -> str:
return f"Hello, {name}!"
# 类型注解仅作为提示,不强制检查
result: int = greeting("Alice") # 不会报错,但IDE可能警告类型不匹配
使用
typing模块支持更复杂的类型:from typing import List, Dict, Optional
def process_data(data: List[Dict[str, int]], default: Optional[int] = None) -> int:
total = 0
for item in data:
total += item.get("value", default or 0)
return total
八、最佳实践与性能优化
1. 函数设计原则
- 单一职责:每个函数只做一件事
- 避免副作用:函数尽量不修改外部状态
- 参数精简:过多参数(>5 个)考虑重构为类或使用配置对象
2. 性能优化技巧
- 避免全局变量:访问局部变量比全局变量快
- 优先使用内置函数:如
sum()、len()比自定义循环效率高 - 生成器替代列表:处理大数据时减少内存占用
# 低效:创建整个列表
def get_squares_list(n):
return [i*i for i in range(n)]
# 高效:使用生成器
def get_squares_generator(n):
for i in range(n):
yield i*i
总结
Python 函数是灵活且强大的编程工具,从基础的参数传递到高级的装饰器和函数式编程,其设计理念贯穿了整个语言。掌握函数的核心概念(作用域、闭包、装饰器)、参数特性(可变参数、解包)及最佳实践,是成为 Python 高级开发者的关键。通过合理设计和使用函数,可以编写出更简洁、更易维护、更高效的代码。
浙公网安备 33010602011771号