函数基础与参数传递详解

3 阅读5分钟

📚 今日学习目标

掌握 Python 函数的核心概念,理解参数传递的多种方式,能够编写可复用的函数代码。


一、什么是函数?

函数是组织好的、可重复使用的代码块,用于实现单一或相关联的功能。Python 提供了许多内置函数(如 print()len()),同时也允许我们自定义函数。

函数的优势

  • 代码复用:一次定义,多次调用
  • 模块化:将复杂问题分解为小问题
  • 可维护性:修改一处,全局生效
  • 可读性:通过函数名表达意图

二、函数的定义与调用

基本语法

def function_name(parameters):
    """文档字符串:描述函数功能"""
    # 函数体
    return result  # 可选

示例:简单的问候函数

def greet(name, greeting="你好"):
    """向指定的人发送问候"""
    message = f"{greeting}{name}!"
    return message

# 调用函数
print(greet("小明"))  # 输出:你好,小明!
print(greet("Alice", "Hello"))  # 输出:Hello,Alice!

三、参数的五种类型

1. 位置参数

按参数位置传递,顺序必须匹配:

def calculate_area(width, height):
    """计算矩形面积"""
    return width * height

# 位置参数调用
area = calculate_area(5, 3)  # width=5, height=3
print(f"面积:{area}")  # 输出:面积:15

2. 默认参数

为参数提供默认值,调用时可省略:

def create_user(username, role="user", active=True):
    """创建用户信息"""
    return {
        "username": username,
        "role": role,
        "active": active
    }

# 使用默认参数
user1 = create_user("zhangsan")
print(user1)  # {'username': 'zhangsan', 'role': 'user', 'active': True}

# 覆盖默认参数
user2 = create_user("admin", role="admin", active=True)
print(user2)  # {'username': 'admin', 'role': 'admin', 'active': True}

3. 关键字参数

通过参数名传递,顺序可以打乱:

def describe_pet(pet_name, animal_type="dog"):
    """描述宠物信息"""
    print(f"我有一只{animal_type},它叫{pet_name}")

# 关键字参数调用
describe_pet(animal_type="cat", pet_name="咪咪")
# 输出:我有一只 cat,它叫咪咪

4. 可变位置参数 (*args)

接收任意数量的位置参数,打包为元组:

def sum_all(*numbers):
    """计算任意数量数字的和"""
    total = 0
    for num in numbers:
        total += num
    return total

print(sum_all(1, 2, 3))  # 输出:6
print(sum_all(1, 2, 3, 4, 5))  # 输出:15
print(sum_all())  # 输出:0

5. 可变关键字参数 (**kwargs)

接收任意数量的关键字参数,打包为字典:

def build_profile(first_name, last_name, **info):
    """构建用户档案"""
    profile = {
        "first_name": first_name,
        "last_name": last_name
    }
    profile.update(info)
    return profile

user = build_profile(
    "John",
    "Doe",
    age=30,
    city="Beijing",
    occupation="Engineer"
)
print(user)
# 输出:{'first_name': 'John', 'last_name': 'Doe', 'age': 30, 'city': 'Beijing', 'occupation': 'Engineer'}

四、参数传递的顺序规则

当混合使用多种参数类型时,必须遵循以下顺序:

def complex_function(pos1, pos2, default1="A", default2="B", *args, **kwargs):
    """
    参数顺序:
    1. 位置参数 (pos1, pos2)
    2. 默认参数 (default1, default2)
    3. 可变位置参数 (*args)
    4. 可变关键字参数 (**kwargs)
    """
    print(f"位置参数:{pos1}, {pos2}")
    print(f"默认参数:{default1}, {default2}")
    print(f"可变位置:{args}")
    print(f"可变关键字:{kwargs}")

# 调用示例
complex_function(1, 2, "X", "Y", 10, 20, 30, key1="value1", key2="value2")

五、返回值与多重返回

单一返回值

def square(x):
    """计算平方"""
    return x * x

result = square(5)
print(result)  # 输出:25

多重返回值(实际返回元组)

def get_user_stats(users):
    """统计用户列表的最大值、最小值和平均值"""
    if not users:
        return None, None, None
    
    max_val = max(users)
    min_val = min(users)
    avg_val = sum(users) / len(users)
    
    return max_val, min_val, avg_val

# 解包返回值
scores = [85, 92, 78, 96, 88]
maximum, minimum, average = get_user_stats(scores)
print(f"最高分:{maximum}, 最低分:{minimum}, 平均分:{average:.2f}")
# 输出:最高分:96, 最低分:78, 平均分:87.80

六、变量作用域

局部变量 vs 全局变量

global_var = "我是全局变量"

def test_scope():
    local_var = "我是局部变量"
    print(f"函数内访问全局:{global_var}")
    print(f"函数内访问局部:{local_var}")

test_scope()
# print(local_var)  # ❌ 错误:局部变量在函数外不可访问

使用 global 修改全局变量

counter = 0

def increment():
    global counter
    counter += 1
    return counter

print(increment())  # 输出:1
print(increment())  # 输出:2
print(increment())  # 输出:3

七、实战案例:计算器函数

def calculator(a, b, operation="+"):
    """
    简易计算器
    
    参数:
        a: 第一个操作数
        b: 第二个操作数
        operation: 运算符 (+, -, *, /, //, %, **)
    
    返回:
        计算结果或错误信息
    """
    operations = {
        "+": lambda x, y: x + y,
        "-": lambda x, y: x - y,
        "*": lambda x, y: x * y,
        "/": lambda x, y: x / y if y != 0 else "错误:除数不能为零",
        "//": lambda x, y: x // y if y != 0 else "错误:除数不能为零",
        "%": lambda x, y: x % y if y != 0 else "错误:除数不能为零",
        "**": lambda x, y: x ** y
    }
    
    if operation not in operations:
        return f"错误:不支持的运算符 '{operation}'"
    
    result = operations[operation](a, b)
    return result

# 测试计算器
print(calculator(10, 5, "+"))  # 输出:15
print(calculator(10, 5, "*"))  # 输出:50
print(calculator(10, 0, "/"))  # 输出:错误:除数不能为零
print(calculator(2, 3, "**"))  # 输出:8

八、最佳实践建议

  1. 函数命名:使用小写字母和下划线,如 calculate_total
  2. 单一职责:一个函数只做一件事
  3. 文档字符串:始终添加 docstring 说明功能
  4. 参数默认值:谨慎使用可变对象作为默认值
  5. 类型提示:Python 3.5+ 推荐使用类型注解
from typing import List, Optional

def find_max(numbers: List[int]) -> Optional[int]:
    """查找列表中的最大值"""
    if not numbers:
        return None
    return max(numbers)

📝 今日总结

知识点关键内容
函数定义def 关键字 + 函数名 + 参数
参数类型位置、默认、关键字、*args、**kwargs
返回值return 语句,可返回多个值
作用域局部变量 vs 全局变量
最佳实践命名规范、单一职责、文档字符串