8Python编程:从入门到实践(第3版)

函数

代码复用

函数定义参数返回值模块

🎯 AI 时代的学习建议:不要只读理论。理解这一章的设计动机(为什么需要这个概念?)和边界条件(什么情况下会失效?)。当 AI 生成的代码涉及这些概念时,你能判断它是否用对了场景。AI 能帮你总结内容,但无法替代你亲手阅读、思考、建立直觉的过程。

第8章:函数(Functions)

一、导读

1.1 本章学习目标

第8章介绍Python的函数机制。本章核心目标:

  • 掌握函数定义和调用:def关键字
  • 理解参数传递:位置参数、关键字参数、默认参数
  • 掌握可变参数:*args和**kwargs
  • 学会使用lambda表达式:匿名函数
  • 理解作用域:局部变量和全局变量
  • 掌握模块导入:import和from...import

1.2 为什么本章如此重要

函数是代码复用的基本单位。Python的函数功能强大,支持多种参数传递方式、闭包、装饰器等高级特性。理解函数的设计原则,才能编写出清晰、可维护的代码。

1.3 核心问题引导

Python的函数参数是如何传递的?是值传递还是引用传递?

*args和**kwargs有什么区别?各自适合什么场景?

lambda表达式和普通函数有什么本质区别?

全局变量和局部变量的作用域规则是什么?


二、核心概念详解

8.1 函数基础

python
# 函数定义
def greet(name, greeting="Hello"):
    """向用户打招呼(文档字符串)"""
    return f"{greeting}, {name}!"

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

# 查看文档
print(greet.__doc__)
help(greet)

8.2 参数传递

python
# 位置参数
def describe_pet(name, animal_type="dog"):
    print(f"I have a {animal_type} named {name}")

describe_pet("Buddy")                    # 使用默认值
describe_pet("Whiskers", "cat")          # 位置参数
describe_pet(animal_type="fish", name="Nemo")  # 关键字参数

# 可变参数 *args
def sum_all(*args):
    """计算所有参数的和"""
    return sum(args)

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

# 关键字可变参数 **kwargs
def build_profile(**kwargs):
    """构建用户档案"""
    return kwargs

profile = build_profile(name="Alice", age=20, city="Beijing")
print(profile)  # {'name': 'Alice', 'age': 20, 'city': 'Beijing'}

# 混合使用
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, 5, x=10, y=20)

8.3 返回值

python
# 返回单个值
def square(x):
    return x ** 2

# 返回多个值(实际返回元组)
def min_max(numbers):
    return min(numbers), max(numbers)

lo, hi = min_max([3, 1, 4, 1, 5])
print(f"Min: {lo}, Max: {hi}")

# 没有return的函数返回None
def do_nothing():
    pass

result = do_nothing()
print(result)  # None

# 提前返回
def divide(a, b):
    if b == 0:
        return None  # 或者抛出异常
    return a / b

8.4 作用域

python
# 局部变量和全局变量
x = 10  # 全局变量

def outer():
    x = 20  # 外层函数的局部变量
    
    def inner():
        nonlocal x  # 引用外层函数的变量
        x = 30
        print(f"inner: x = {x}")
    
    inner()
    print(f"outer: x = {x}")

outer()
print(f"global: x = {x}")

# global关键字
count = 0

def increment():
    global count
    count += 1

increment()
increment()
print(count)  # 2

# 最佳实践:尽量避免使用global
def better_increment(current_count):
    return current_count + 1

count = better_increment(count)

8.5 Lambda表达式

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

# 多参数
add = lambda a, b: a + b
print(add(3, 5))  # 8

# 与高阶函数配合
numbers = [1, 2, 3, 4, 5]

# map
squared = list(map(lambda x: x**2, numbers))
print(squared)  # [1, 4, 9, 16, 25]

# filter
evens = list(filter(lambda x: x % 2 == 0, numbers))
print(evens)  # [2, 4]

# sorted
students = [("Alice", 90), ("Bob", 85), ("Charlie", 92)]
sorted_students = sorted(students, key=lambda s: s[1], reverse=True)
print(sorted_students)

# 立即调用的lambda
result = (lambda x, y: x + y)(3, 5)
print(result)  # 8

8.6 模块

python
# 导入整个模块
import math
print(math.sqrt(16))  # 4.0
print(math.pi)        # 3.14159...

# 导入特定函数
from math import sqrt, pi
print(sqrt(16))

# 导入并重命名
from datetime import datetime as dt
now = dt.now()
print(now)

# 导入所有(不推荐)
# from math import *

# 自定义模块
# 假设 mymodule.py 中有:
# def add(a, b):
#     return a + b
# PI = 3.14159

# import mymodule
# print(mymodule.add(1, 2))
# print(mymodule.PI)

三、实战案例

3.1 装饰器

python
import time
import functools

def timer(func):
    """计时装饰器"""
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        start = time.time()
        result = func(*args, **kwargs)
        end = time.time()
        print(f"{func.__name__} took {end - start:.4f}s")
        return result
    return wrapper

def memoize(func):
    """缓存装饰器"""
    cache = {}
    @functools.wraps(func)
    def wrapper(*args):
        if args not in cache:
            cache[args] = func(*args)
        return cache[args]
    return wrapper

@timer
@memoize
def fibonacci(n):
    if n < 2:
        return n
    return fibonacci(n - 1) + fibonacci(n - 2)

print(fibonacci(30))

四、本章小结

第8章介绍了Python函数:定义和调用、参数传递(位置/关键字/默认/可变)、返回值、作用域、lambda表达式、模块导入。函数是代码复用的核心。


五、思考与练习

思考题

Python的函数参数传递机制是什么?

*args和**kwargs在函数定义和调用时有什么不同?

闭包是什么?lambda能形成闭包吗?

装饰器的原理是什么?

编程练习

实现一个带参数验证的函数装饰器。

编写一个递归函数计算阶乘。

实现一个简单的缓存装饰器。


8/11函数
0%