Skip to content

函数

函数是组织好的、可重复使用的代码块,用于实现特定功能。Python 提供了灵活的函数定义方式。

函数定义

基本语法

python
# 定义函数
def greet():
    """问候函数"""
    print("Hello, Python!")

# 调用函数
greet()

# 带参数的函数
def greet_person(name):
    """问候指定的人"""
    print(f"Hello, {name}!")

greet_person("张三")

# 带返回值的函数
def add(a, b):
    """两数相加"""
    return a + b

result = add(10, 20)
print(f"结果:{result}")

# 多个返回值
def get_info():
    """返回多个值"""
    name = "张三"
    age = 25
    return name, age

n, a = get_info()
print(f"姓名:{n},年龄:{a}")

文档字符串

python
def calculate_area(width, height):
    """
    计算矩形面积
    
    参数:
        width: 矩形的宽度
        height: 矩形的高度
    
    返回:
        矩形的面积
    
    示例:
        >>> calculate_area(5, 3)
        15
    """
    return width * height

# 访问文档字符串
print(calculate_area.__doc__)

# 使用 help() 查看帮助
# help(calculate_area)

参数类型

位置参数

python
# 位置参数:按顺序传递
def power(base, exp):
    """计算 base 的 exp 次方"""
    return base ** exp

print(power(2, 3))  # 8

# 必须传递所有位置参数
# power(2)  # TypeError

默认参数

python
# 默认参数:有默认值的参数
def greet(name, greeting="Hello"):
    """带默认值的问候"""
    print(f"{greeting}, {name}!")

greet("张三")                # Hello, 张三!
greet("李四", "Hi")          # Hi, 李四!

# 默认参数必须在位置参数之后
# def greet(greeting="Hello", name):  # 语法错误
#     pass

# 默认参数的陷阱(可变对象)
def add_item(item, items=[]):  # 危险!
    items.append(item)
    return items

print(add_item("a"))  # ['a']
print(add_item("b"))  # ['a', 'b'](不是预期的结果)

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

print(add_item_safe("a"))  # ['a']
print(add_item_safe("b"))  # ['b']

关键字参数

python
# 关键字参数:通过参数名传递
def create_profile(name, age, city):
    """创建个人信息"""
    return {"name": name, "age": age, "city": city}

# 使用关键字参数(顺序可以改变)
profile1 = create_profile(name="张三", age=25, city="北京")
profile2 = create_profile(age=30, city="上海", name="李四")
profile3 = create_profile("王五", city="广州", age=28)  # 混合使用

print(profile1)
print(profile2)
print(profile3)

可变参数

python
# *args:接收任意数量的位置参数(元组)
def sum_all(*args):
    """计算所有参数的和"""
    total = 0
    for num in args:
        total += num
    return total

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

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

print_info(name="张三", age=25, city="北京")

# 混合使用
def func(a, b, *args, **kwargs):
    print(f"a={a}, b={b}")
    print(f"args={args}")
    print(f"kwargs={kwargs}")

func(1, 2, 3, 4, x=5, y=6)
# a=1, b=2
# args=(3, 4)
# kwargs={'x': 5, 'y': 6}

# 解包传递
numbers = [1, 2, 3, 4, 5]
print(sum_all(*numbers))  # 解包列表

info = {"name": "李四", "age": 30}
print_info(**info)  # 解包字典

仅限关键字参数

python
# * 后面的参数必须使用关键字传递
def greet(name, *, greeting="Hello"):
    """greeting 必须使用关键字传递"""
    print(f"{greeting}, {name}!")

greet("张三", greeting="Hi")  # 正确
# greet("张三", "Hi")  # 错误

# / 前面的参数必须使用位置传递(Python 3.8+)
def greet_new(name, /, greeting="Hello"):
    """name 必须使用位置传递"""
    print(f"{greeting}, {name}!")

greet_new("张三")  # 正确
# greet_new(name="张三")  # 错误

作用域

变量作用域

python
# 局部变量
def my_function():
    local_var = 10  # 局部变量
    print(local_var)

my_function()
# print(local_var)  # NameError

# 全局变量
global_var = 100

def access_global():
    print(global_var)  # 可以访问

access_global()

# 修改全局变量需要使用 global
def modify_global():
    global global_var
    global_var = 200

modify_global()
print(global_var)  # 200

# 嵌套函数的作用域
def outer():
    x = 10
    
    def inner():
        nonlocal x  # 引用外层函数的变量
        x = 20
    
    inner()
    print(x)  # 20

outer()

作用域规则(LEGB)

python
# LEGB 规则:查找顺序
# Local → Enclosing → Global → Built-in

x = "global"

def outer():
    x = "enclosing"
    
    def inner():
        x = "local"
        print(x)  # local
    
    inner()
    print(x)  # enclosing

outer()
print(x)  # global

# 内置作用域
print(len([1, 2, 3]))  # 使用内置函数 len

# 不要覆盖内置函数
# len = 100  # 危险!
# print(len([1, 2, 3]))  # TypeError

高阶函数

函数作为参数

python
# 函数作为参数传递
def apply_operation(x, y, operation):
    """对 x 和 y 应用指定操作"""
    return operation(x, y)

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

def multiply(a, b):
    return a * b

print(apply_operation(5, 3, add))      # 8
print(apply_operation(5, 3, multiply)) # 15

# 使用内置函数
numbers = [1, 2, 3, 4, 5]
print(list(map(str, numbers)))  # ['1', '2', '3', '4', '5']
print(list(filter(lambda x: x > 2, numbers)))  # [3, 4, 5]

函数作为返回值

python
# 返回函数
def get_multiplier(factor):
    """返回一个乘法函数"""
    def multiplier(x):
        return x * factor
    return multiplier

double = get_multiplier(2)
triple = get_multiplier(3)

print(double(5))  # 10
print(triple(5))  # 15

# 闭包:函数和其引用的环境变量
def make_counter():
    """创建计数器"""
    count = 0
    
    def counter():
        nonlocal count
        count += 1
        return count
    
    return counter

counter1 = make_counter()
print(counter1())  # 1
print(counter1())  # 2

counter2 = make_counter()
print(counter2())  # 1(独立的计数器)

Lambda 表达式

基本语法

python
# lambda 参数: 表达式
# 匿名函数,只能有一个表达式

# 简单示例
add = lambda a, b: a + b
print(add(3, 5))  # 8

square = lambda x: x ** 2
print(square(5))  # 25

# 条件表达式
is_even = lambda x: "偶数" if x % 2 == 0 else "奇数"
print(is_even(4))  # 偶数

常见应用

python
# 排序
students = [
    {"name": "张三", "age": 25},
    {"name": "李四", "age": 20},
    {"name": "王五", "age": 30}
]

# 按年龄排序
sorted_students = sorted(students, key=lambda s: s["age"])
print(sorted_students)

# 按姓名排序
sorted_by_name = sorted(students, key=lambda s: s["name"])
print(sorted_by_name)

# 过滤
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
evens = list(filter(lambda x: x % 2 == 0, numbers))
print(evens)  # [2, 4, 6, 8, 10]

# 映射
squares = list(map(lambda x: x ** 2, numbers))
print(squares)

# reduce
from functools import reduce
total = reduce(lambda a, b: a + b, numbers)
print(total)  # 55

装饰器

基本概念

python
# 装饰器:修改或增强函数功能的函数
def my_decorator(func):
    """装饰器函数"""
    def wrapper():
        print("函数执行前")
        func()
        print("函数执行后")
    return wrapper

# 使用装饰器
@my_decorator
def say_hello():
    print("Hello!")

say_hello()
# 输出:
# 函数执行前
# Hello!
# 函数执行后

带参数的装饰器

python
def my_decorator(func):
    """处理任意参数的装饰器"""
    def wrapper(*args, **kwargs):
        print(f"调用 {func.__name__}")
        result = func(*args, **kwargs)
        print(f"返回 {result}")
        return result
    return wrapper

@my_decorator
def add(a, b):
    return a + b

result = add(3, 5)
# 调用 add
# 返回 8

常用装饰器示例

python
import time
from functools import wraps

# 计时装饰器
def timer(func):
    """计算函数执行时间"""
    @wraps(func)  # 保留原函数的元信息
    def wrapper(*args, **kwargs):
        start = time.time()
        result = func(*args, **kwargs)
        end = time.time()
        print(f"{func.__name__} 执行时间:{end - start:.4f}秒")
        return result
    return wrapper

@timer
def slow_function():
    time.sleep(1)
    return "完成"

slow_function()

# 日志装饰器
def logger(func):
    """记录函数调用"""
    @wraps(func)
    def wrapper(*args, **kwargs):
        print(f"调用 {func.__name__},参数:{args}, {kwargs}")
        result = func(*args, **kwargs)
        print(f"返回:{result}")
        return result
    return wrapper

@logger
def greet(name):
    return f"Hello, {name}!"

greet("张三")

类装饰器

python
# 使用类作为装饰器
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 say_hello():
    print("Hello!")

say_hello()
say_hello()
say_hello()

递归

递归函数

python
# 递归:函数调用自身

# 计算阶乘
def factorial(n):
    """计算 n 的阶乘"""
    if n <= 1:
        return 1
    return n * factorial(n - 1)

print(f"5! = {factorial(5)}")  # 120

# 斐波那契数列
def fibonacci(n):
    """第 n 个斐波那契数"""
    if n <= 2:
        return 1
    return fibonacci(n - 1) + fibonacci(n - 2)

# 打印前 10 个斐波那契数
print([fibonacci(i) for i in range(1, 11)])

# 汉诺塔
def hanoi(n, source, auxiliary, target):
    """汉诺塔问题"""
    if n == 1:
        print(f"移动盘子 1 从 {source}{target}")
        return
    hanoi(n - 1, source, target, auxiliary)
    print(f"移动盘子 {n}{source}{target}")
    hanoi(n - 1, auxiliary, source, target)

hanoi(3, "A", "B", "C")

# 递归深度限制
import sys
print(f"默认递归深度:{sys.getrecursionlimit()}")
# sys.setrecursionlimit(2000)  # 可以修改

小结

本章我们学习了:

  • 函数定义:def、return、文档字符串
  • 参数类型:位置参数、默认参数、关键字参数、可变参数
  • 作用域:局部变量、全局变量、LEGB 规则
  • 高阶函数:函数作为参数和返回值
  • Lambda 表达式:匿名函数
  • 装饰器:修改或增强函数功能
  • 递归:函数调用自身

下一章,我们将学习 列表与元组,了解 Python 中重要的数据结构。