Skip to content

6.1 函数定义与调用语法

在Python中,函数就像一个魔法盒子,你把东西放进去(输入参数),它就会按照设定好的规则处理,然后给你返回结果。函数的定义使用def关键字,后面跟着函数名和括号,括号里可以有参数,最后以冒号结束。函数体需要缩进,通常会包含一些处理逻辑,最后可能用return语句返回结果。

python
# 定义一个简单的打招呼函数
def greet(name):
    # name是参数,函数内部可以使用
    message = f"你好, {name}!"  # 创建问候消息
    return message  # 返回消息

# 调用函数
result = greet("小明")  # 传入参数"小明"
print(result)  # 输出: 你好, 小明!

这里的关键点是:定义函数时用def,调用时直接写函数名加括号和参数。函数可以让代码复用,避免重复写相同的逻辑,简直是程序员的得力助手!

6.2 函数参数传递方式

Python中的参数传递有点像快递包裹,你寄出去的东西(实参)会被送到函数那里(形参)。主要有两种方式:位置参数和关键字参数。位置参数按顺序对应,关键字参数则通过参数名指定,更清晰但要注意顺序。

功能名称实例调用方法具体功能、注意事项、必需参数/可选参数
位置参数传递func(a, b)按参数定义顺序传递,必需参数必须提供
关键字参数传递func(param1=a, param2=b)通过参数名指定值,可读性高,顺序可变
python
# 定义一个计算矩形面积的函数
def calculate_area(length, width):
    # length和width是位置参数
    if length <= 0 or width <= 0:
        raise ValueError("长度和宽度必须为正数")  # 错误捕获
    return length * width

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

# 使用关键字参数调用
area2 = calculate_area(width=4, length=6)  # 顺序可变
print(f"面积2: {area2}")  # 输出: 面积2: 24

# 混合使用(位置参数在前,关键字参数在后)
try:
    area3 = calculate_area(7, width=2)  # 合法
    print(f"面积3: {area3}")  # 输出: 面积3: 14
except ValueError as e:
    print(f"错误: {e}")

注意:位置参数必须放在关键字参数前面,否则会报错。而且所有必需参数都必须被赋值,不然函数会抱怨!

6.3 返回值与无返回值函数

函数的返回值就像任务完成后的成果报告。如果函数有return语句,它会把结果带回来;如果没有return或者return后面没东西,函数就默认返回None,表示“没啥好说的”。

功能名称实例调用方法具体功能、注意事项、必需参数/可选参数
有返回值函数result = func()返回指定值,可用于后续计算
无返回值函数func()返回None,通常用于执行操作而非计算
python
# 有返回值的函数:计算平方
def square(x):
    return x * x  # 返回计算结果

# 无返回值的函数:打印日志
def log_message(message):
    print(f"[日志] {message}")  # 执行操作,无return

# 调用有返回值函数
num = 4
squared = square(num)  # 获取返回值
print(f"{num}的平方是{squared}")  # 输出: 4的平方是16

# 调用无返回值函数
log_result = log_message("程序启动")  # 执行打印
print(f"log_message的返回值: {log_result}")  # 输出: log_message的返回值: None

# 注意:即使不捕获返回值,函数也会执行
square(5)  # 计算但不保存结果,浪费了!

这里的小窍门是:如果你需要函数的结果,一定要用变量接收返回值;如果只是执行某个动作(比如打印或写文件),那就不需要关心返回值。

6.4 默认参数与关键字参数

默认参数就像是函数的“备胎”,当你不提供某个参数时,它就自动顶上。关键字参数则让你在调用时明确指定参数名,代码更易读。两者结合使用,能让函数更灵活,调用更方便。

功能名称实例调用方法具体功能、注意事项、必需参数/可选参数
默认参数设置def func(a, b=10)b有默认值10,调用时可省略
关键字参数调用func(a=5, b=20)明确指定参数名,顺序无关
python
# 定义一个发送邮件的函数,带默认参数
def send_email(to, subject="无主题", body=""):
    # to是必需参数,subject和body有默认值
    if not to:
        raise ValueError("收件人地址不能为空")  # 错误捕获
    email_content = f"收件人: {to}\n主题: {subject}\n内容: {body}"
    return email_content  # 返回邮件内容

# 只提供必需参数,使用默认值
email1 = send_email("user@example.com")
print(email1)
# 输出:
# 收件人: user@example.com
# 主题: 无主题
# 内容: 

# 提供部分参数,覆盖默认值
email2 = send_email("boss@example.com", subject="项目更新")
print(email2)
# 输出:
# 收件人: boss@example.com
# 主题: 项目更新
# 内容: 

# 使用关键字参数,顺序自由
try:
    email3 = send_email(body="详情见附件", to="client@example.com", subject="报价单")
    print(email3)
    # 输出:
    # 收件人: client@example.com
    # 主题: 报价单
    # 内容: 详情见附件
except ValueError as e:
    print(f"错误: {e}")

# 注意:默认参数如果是可变对象(如列表),要小心!
def add_item(item, target_list=[]):  # 危险!默认列表是共享的
    target_list.append(item)
    return target_list

# 测试可变默认参数的问题
list1 = add_item("苹果")
list2 = add_item("香蕉")
print(f"list1: {list1}, list2: {list2}")  # 输出: list1: ['苹果', '香蕉'], list2: ['苹果', '香蕉']
# 哦不!两个列表竟然共享了同一个默认列表,这可不是我们想要的。

重要提醒:默认参数如果是可变对象(比如列表、字典),会在多次调用间共享状态,容易出bug。安全做法是用None作为默认值,然后在函数内部初始化。例如:

python
# 安全的可变默认参数处理
def safe_add_item(item, target_list=None):
    if target_list is None:
        target_list = []  # 每次调用都创建新列表
    target_list.append(item)
    return target_list

# 测试安全版本
safe_list1 = safe_add_item("橙子")
safe_list2 = safe_add_item("葡萄")
print(f"safe_list1: {safe_list1}, safe_list2: {safe_list2}")  # 输出: safe_list1: ['橙子'], safe_list2: ['葡萄']
# 这样就各自独立了,完美!