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 高级开发者的关键。通过合理设计和使用函数,可以编写出更简洁、更易维护、更高效的代码。

posted on 2025-07-09 14:52  小陶coding  阅读(144)  评论(0)    收藏  举报