Skip to content

函数基础

让代码可复用 —— 从重复劳动到优雅编程


什么是函数?

函数是可重复使用的代码块,接受输入(参数),执行操作,返回输出(结果)。

类比

  • Stata: program define
  • R: function()
  • 数学: f(x) = 2x + 1

为什么需要函数?

  • 避免重复代码(DRY 原则:Don't Repeat Yourself)
  • 代码更易维护
  • 提高可读性
  • 便于测试和调试

定义函数

基本语法

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

示例 1:简单函数

python
def greet():
    """打印问候语"""
    print("Hello, World!")

# 调用函数
greet()  # 输出: Hello, World!

示例 2:带参数的函数

python
def greet_person(name):
    """根据姓名打印问候语"""
    print(f"Hello, {name}!")

greet_person("Alice")  # 输出: Hello, Alice!
greet_person("Bob")    # 输出: Hello, Bob!

示例 3:带返回值的函数

python
def calculate_bmi(weight, height):
    """计算BMI

    参数:
        weight: 体重(千克)
        height: 身高(米)

    返回:
        BMI值
    """
    bmi = weight / (height ** 2)
    return bmi

# 使用函数
result = calculate_bmi(70, 1.75)
print(f"BMI: {result:.2f}")  # BMI: 22.86

对比:Stata vs R vs Python

Stata 版本

stata
* Stata
program define calc_bmi
    args weight height
    gen bmi = `weight' / (`height'^2)
end

R 版本

r
# R
calc_bmi <- function(weight, height) {
  bmi <- weight / (height^2)
  return(bmi)
}

result <- calc_bmi(70, 1.75)

Python 版本

python
# Python
def calc_bmi(weight, height):
    bmi = weight / (height ** 2)
    return bmi

result = calc_bmi(70, 1.75)

实战案例

案例 1:收入税计算

python
def calculate_tax(income):
    """计算个人所得税(累进税率)

    税率:
        0-50000: 10%
        50001-100000: 20%
        100001+: 30%
    """
    if income <= 50000:
        tax = income * 0.10
    elif income <= 100000:
        tax = 50000 * 0.10 + (income - 50000) * 0.20
    else:
        tax = 50000 * 0.10 + 50000 * 0.20 + (income - 100000) * 0.30

    return tax

# 使用
incomes = [45000, 75000, 120000]
for income in incomes:
    tax = calculate_tax(income)
    net = income - tax
    print(f"收入: ${income:,}, 税: ${tax:,.0f}, 税后: ${net:,.0f}")

案例 2:数据验证

python
def validate_age(age):
    """验证年龄是否合理

    返回:
        (is_valid, message): 布尔值和提示信息
    """
    if age < 0:
        return False, "年龄不能为负数"
    elif age > 120:
        return False, "年龄过大"
    elif age < 18:
        return False, "未成年"
    else:
        return True, "年龄有效"

# 使用
ages = [25, -5, 150, 15, 30]
for age in ages:
    is_valid, message = validate_age(age)
    status = "" if is_valid else ""
    print(f"{status} 年龄 {age}: {message}")

案例 3:描述性统计

python
def describe_data(data):
    """计算描述性统计

    返回字典包含: n, mean, median, min, max
    """
    n = len(data)
    mean = sum(data) / n
    sorted_data = sorted(data)
    median = sorted_data[n // 2]

    return {
        'n': n,
        'mean': mean,
        'median': median,
        'min': min(data),
        'max': max(data)
    }

# 使用
scores = [85, 92, 78, 90, 88, 76, 95, 82]
stats = describe_data(scores)

print(f"样本量: {stats['n']}")
print(f"平均分: {stats['mean']:.2f}")
print(f"中位数: {stats['median']}")
print(f"最低分: {stats['min']}")
print(f"最高分: {stats['max']}")

返回值

1. 返回单个值

python
def square(x):
    return x ** 2

result = square(5)  # 25

2. 返回多个值(元组)

python
def calculate_stats(data):
    mean = sum(data) / len(data)
    maximum = max(data)
    minimum = min(data)
    return mean, maximum, minimum  # 自动打包为元组

# 解包接收
avg, max_val, min_val = calculate_stats([1, 2, 3, 4, 5])
print(avg, max_val, min_val)  # 3.0 5 1

3. 返回字典

python
def get_student_info(name, age, major):
    return {
        'name': name,
        'age': age,
        'major': major,
        'status': 'active'
    }

student = get_student_info("Alice", 25, "Economics")
print(student['name'])  # Alice

4. 无返回值

python
def print_report(data):
    """只打印,不返回"""
    for item in data:
        print(item)
    # 没有 return 语句,默认返回 None

result = print_report([1, 2, 3])
print(result)  # None

函数参数类型

1. 位置参数

python
def power(base, exponent):
    return base ** exponent

result = power(2, 3)  # 2^3 = 8

2. 默认参数

python
def greet(name, greeting="Hello"):
    """greeting 有默认值"""
    return f"{greeting}, {name}!"

print(greet("Alice"))              # Hello, Alice!
print(greet("Bob", "Hi"))          # Hi, Bob!
print(greet("Carol", greeting="Hey"))  # Hey, Carol!

3. 关键字参数

python
def register_student(name, age, major, gpa=3.0):
    print(f"{name}, {age}岁, 专业: {major}, GPA: {gpa}")

# 位置传参
register_student("Alice", 25, "Economics")

# 关键字传参(顺序可变)
register_student(major="Sociology", age=28, name="Bob", gpa=3.5)

# 混合(位置参数必须在前)
register_student("Carol", 26, major="Political Science")

4. 可变参数(*args)

python
def calculate_average(*numbers):
    """接受任意数量的数字"""
    if not numbers:
        return 0
    return sum(numbers) / len(numbers)

print(calculate_average(1, 2, 3))           # 2.0
print(calculate_average(10, 20, 30, 40))    # 25.0
print(calculate_average(5))                 # 5.0

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

python
def create_respondent(**info):
    """接受任意数量的关键字参数"""
    for key, value in info.items():
        print(f"{key}: {value}")

create_respondent(
    name="Alice",
    age=30,
    income=75000,
    education="Master's"
)

最佳实践

1. 函数命名

python
#  不好的命名
def f(x, y):
    return x + y

#  好的命名(动词开头,描述功能)
def calculate_total(price, quantity):
    return price * quantity

def validate_email(email):
    return '@' in email

def is_adult(age):
    return age >= 18

2. 单一职责原则

python
#  函数做太多事
def process_data(data):
    # 清洗数据
    # 计算统计
    # 生成图表
    # 保存结果
    pass

#  拆分为多个函数
def clean_data(data):
    """只负责清洗"""
    pass

def calculate_stats(data):
    """只负责计算"""
    pass

def plot_data(data):
    """只负责画图"""
    pass

3. 文档字符串

python
def calculate_correlation(x, y):
    """计算两个变量的相关系数

    参数:
        x (list): 第一个变量的数据
        y (list): 第二个变量的数据

    返回:
        float: 相关系数 (-1 到 1)

    示例:
        >>> calculate_correlation([1, 2, 3], [2, 4, 6])
        1.0
    """
    # 函数实现
    pass

练习题

练习 1:温度转换

python
# 编写两个函数:
# 1. celsius_to_fahrenheit(c): 摄氏转华氏
# 2. fahrenheit_to_celsius(f): 华氏转摄氏
# 公式: F = C × 9/5 + 32

练习 2:成绩评级

python
# 编写函数 grade_to_letter(score)
# 90-100: A
# 80-89: B
# 70-79: C
# 60-69: D
# <60: F

练习 3:列表统计

python
# 编写函数 analyze_scores(scores)
# 返回字典包含:
# - count: 数量
# - mean: 平均分
# - passing_rate: 及格率(>=60)
# - grade_distribution: 各等级人数

scores = [85, 92, 78, 65, 90, 55, 88, 76, 95, 70]
result = analyze_scores(scores)

下一步

在下一节中,我们将学习 函数参数的高级用法,包括参数解包、lambda 函数等。

继续前进!

基于 MIT 许可证发布。内容版权归作者所有。