Z
ZHANK
函数与模块

函数基础

学会定义函数、参数传递、返回值和文档字符串

函数基础

函数是把一段代码打包起来、可以反复调用的工具。它是编程中最核心的抽象手段。

学完本章你将掌握: 定义函数、参数类型、返回值、作用域、以及 Python 特有的参数技巧。


一、为什么需要函数

没有函数时,代码重复、难维护:

python
# 不用函数:同样的逻辑写三遍
print("===== 小明 =====")
print("开始处理...")
print("处理完成!")

print("===== 小红 =====")
print("开始处理...")
print("处理完成!")

print("===== 小刚 =====")
print("开始处理...")
print("处理完成!")

用函数后,简洁且易修改:

python
def process_user(name):
    print(f"===== {name} =====")
    print("开始处理...")
    print("处理完成!")

process_user("小明")
process_user("小红")
process_user("小刚")

二、定义和调用函数

python
# def 关键字定义
def greet():
    print("你好!")

# 调用函数
greet()

带参数的函数:

python
def greet_user(name):
    print(f"你好,{name}!")

greet_user("小明")
greet_user("小红")

💡 参数 vs 实参:定义时的 name形参,调用时传的 "小明"实参


三、返回值

python
def add(a, b):
    return a + b

result = add(3, 5)
print(result)  # 8

# 返回多个值(实际是返回元组)
def get_user_info():
    return "小明", 20, "北京"

name, age, city = get_user_info()  # 拆包接收
print(name, age, city)

# 提前返回(常用模式)
def check_age(age):
    if age < 0:
        return "无效年龄"
    if age < 18:
        return "未成年人"
    return "成年人"

print(check_age(25))  # 成年人

💡 函数没有 return 时,默认返回 None。 这就是为什么 print(print("hello")) 会输出 None


四、参数类型

位置参数(最常用)

python
def describe(name, age, city):
    print(f"{name}{age}岁,来自{city}")

describe("小明", 20, "北京")

默认参数

python
def greet(name, greeting="你好"):
    print(f"{greeting}{name}!")

greet("小明")                       # 你好,小明!
greet("小明", greeting="早上好")     # 早上好,小明!

⚠️ 默认参数陷阱:默认值不要用可变对象!

python
# ❌ 错误做法
def add_item(item, items=[]):
    items.append(item)
    return items

print(add_item("a"))  # ['a']
print(add_item("b"))  # ['a', 'b'] ← 累积了!不是预期的!

# ✅ 正确做法
def add_item(item, items=None):
    if items is None:
        items = []
    items.append(item)
    return items

关键字参数

python
def order(item, quantity=1, price=0):
    return f"购买 {quantity}{item},共 {quantity * price} 元"

# 按名称传参,顺序任意
print(order(quantity=3, price=10, item="苹果"))

仅限关键字参数(Python 3+)

python
def config(*, host, port, debug=False):
    print(f"连接 {host}:{port},调试: {debug}")

config(host="localhost", port=8000)
# config("localhost", 8000)  # 报错,必须使用关键字

五、*args 和 **kwargs

接收任意数量的参数:

python
# *args:接收任意数量的位置参数(打包为元组)
def sum_all(*args):
    total = 0
    for n in args:
        total += n
    return total

print(sum_all(1, 2, 3))       # 6
print(sum_all(1, 2, 3, 4, 5)) # 15

# **kwargs:接收任意数量的关键字参数(打包为字典)
def print_info(**kwargs):
    for key, value in kwargs.items():
        print(f"{key}: {value}")

print_info(name="小明", age=20, city="北京")
python
# 实际应用:通用的日志函数
def log(message, **metadata):
    print(f"[日志] {message}")
    for k, v in metadata.items():
        print(f"  {k}: {v}")

log("用户登录", user="小明", ip="192.168.1.1", status="成功")

六、函数注解(类型提示)

Python 3.5+ 支持类型提示(不影响运行,但提升代码可读性):

python
def greet(name: str, age: int) -> str:
    return f"{name}{age}岁"

print(greet("小明", 20))

# 完整的类型提示
from typing import List, Dict, Optional

def process_scores(
    students: List[str],
    scores: Dict[str, float],
    bonus: Optional[int] = None
) -> Dict[str, float]:
    result = {}
    for name in students:
        score = scores.get(name, 0)
        if bonus:
            score += bonus
        result[name] = score
    return result

七、文档字符串 (docstring)

python
def calculate_bmi(weight: float, height: float) -> str:
    """
    计算 BMI 指数并返回健康建议。

    参数:
        weight: 体重(kg)
        height: 身高(m)

    返回:
        健康建议字符串

    示例:
        >>> calculate_bmi(70, 1.75)
        '正常体重'
    """
    bmi = weight / (height ** 2)
    if bmi < 18.5:
        return "偏瘦"
    elif bmi < 24:
        return "正常体重"
    else:
        return "偏胖"

# 查看文档
print(calculate_bmi.__doc__)

八、作用域

python
total = 100  # 全局变量

def calculate():
    local = 50  # 局部变量
    print(f"可以读全局变量: {total}")
    print(f"局部变量: {local}")

calculate()
# print(local)  # ❌ NameError:不能访问局部变量

# 函数内修改全局变量要用 global
counter = 0

def increment():
    global counter
    counter += 1

increment()
print(counter)  # 1

小结

  1. def 定义函数,return 返回结果
  2. 参数类型:位置参数、默认参数、关键字参数、*args**kwargs
  3. 类型提示 (str, int) 提升可读性,不强制检查
  4. 默认参数不要用可变对象
  5. 函数内变量是局部的,要用全局变量时加 global

小练习

  1. 写一个函数 is_prime(n) 判断一个数是否为质数
  2. 写一个函数 max_of_three(a, b, c) 返回三个数中的最大值
  3. 写一个函数 count_words(text) 统计一段文字中每个单词的出现次数(回顾字典!)

💬 下一章预告:学完函数基础,下一章学习异常处理——让程序优雅地应对错误而不崩溃。