Skip to content

第二章练习答案 ​

本页提供第二章所有练习的参考答案和详细解释。

00-function-basics ​

练习 1:温度转换 ​

python
def celsius_to_fahrenheit(c):
    return c * 9/5 + 32

def fahrenheit_to_celsius(f):
    return (f - 32) * 5/9

print(celsius_to_fahrenheit(0))    # 32.0
print(celsius_to_fahrenheit(100))  # 212.0
print(fahrenheit_to_celsius(32))   # 0.0
print(fahrenheit_to_celsius(212))  # 100.0

练习 2:默认参数 ​

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

print(power(3))      # 9
print(power(2, 10))  # 1024

练习 3:默认值陷阱 ​

python
# 原代码问题
def append_to(element, target=[]):
    target.append(element)
    return target

list1 = append_to(1)  # [1]
list2 = append_to(2)  # [1, 2],不是 [2]!

# 解释:默认值 [] 在函数定义时创建一次,所有调用共享

# 修复
def append_to(element, target=None):
    if target is None:
        target = []
    target.append(element)
    return target

list1 = append_to(1)  # [1]
list2 = append_to(2)  # [2]

练习 4:多返回值 ​

python
def min_max(numbers):
    return min(numbers), max(numbers)

minimum, maximum = min_max([3, 1, 4, 1, 5, 9, 2, 6])
print(f"Min: {minimum}, Max: {maximum}")  # Min: 1, Max: 9

练习 5:函数作为参数 ​

python
def apply_operation(func, numbers):
    return [func(n) for n in numbers]

def double(x):
    return x * 2

print(apply_operation(double, [1, 2, 3, 4]))  # [2, 4, 6, 8]

01-scope-and-legb ​

练习 1:预测输出 ​

python
x = 10

def func():
    x = 20
    print(f"Inside func: {x}")

func()  # Inside func: 20
print(f"Outside func: {x}")  # Outside func: 10

解释:函数内的 x 是本地变量,不影响全局 x。

练习 2:全局计数器 ​

python
counter = 0

def increment_global():
    global counter
    counter += 1

def reset_global():
    global counter
    counter = 0

increment_global()
increment_global()
print(counter)  # 2
reset_global()
print(counter)  # 0

练习 3:nonlocal 实践 ​

python
def make_counter():
    count = 0
    
    def increment():
        nonlocal count  # 关键修复
        count = count + 1
        return count
    
    return increment

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

练习 4:LEGB 顺序 ​

python
x = "global"

def outer():
    x = "outer"
    
    def middle():
        x = "middle"
        
        def inner():
            print(x)  # (1) "middle" - 找到 middle 的 x
        
        inner()
        print(x)  # (2) "middle" - 本地 x
    
    middle()
    print(x)  # (3) "outer" - 本地 x

outer()
print(x)  # (4) "global" - 全局 x

输出:

middle
middle
outer
global

练习 5:避免内置名字 ​

python
# 问题:list 和 sum 是内置名字
def calculate_length(list):  # 覆盖了内置 list
    sum = 0  # 覆盖了内置 sum
    for item in list:
        sum = sum + 1
    return sum

# 修复:使用不同的变量名
def calculate_length(items):
    total = 0
    for item in items:
        total = total + 1
    return total

# 或直接使用内置 len
def calculate_length(items):
    return len(items)

02-closures-and-nonlocal ​

练习 1:温度转换器工厂 ​

python
def make_converter(from_unit, to_unit):
    if from_unit == 'C' and to_unit == 'F':
        def convert(temp):
            return temp * 9/5 + 32
    elif from_unit == 'F' and to_unit == 'C':
        def convert(temp):
            return (temp - 32) * 5/9
    else:
        def convert(temp):
            return temp
    return convert

c_to_f = make_converter('C', 'F')
print(c_to_f(0))    # 32.0
print(c_to_f(100))  # 212.0

练习 2:计数器三件套 ​

python
def make_counter():
    count = 0
    
    def increment():
        nonlocal count
        count += 1
        return count
    
    def decrement():
        nonlocal count
        count -= 1
        return count
    
    def value():
        return count
    
    return increment, decrement, value

inc, dec, val = make_counter()
inc()
inc()
dec()
print(val())  # 1

练习 3:修复闭包陷阱 ​

python
# 原代码问题
def make_multipliers():
    return [lambda x: x * i for i in range(5)]

funcs = make_multipliers()
print([f(2) for f in funcs])  # [8, 8, 8, 8, 8],不是 [0, 2, 4, 6, 8]

# 解释:所有 lambda 捕获同一个变量 i,循环结束时 i=4

# 修复方法 1:默认参数
def make_multipliers():
    return [lambda x, i=i: x * i for i in range(5)]

# 修复方法 2:额外闭包层
def make_multipliers():
    def make_func(n):
        return lambda x: x * n
    return [make_func(i) for i in range(5)]

funcs = make_multipliers()
print([f(2) for f in funcs])  # [0, 2, 4, 6, 8]

练习 4:累加器 ​

python
def make_accumulator():
    total = 0
    
    def add(n):
        nonlocal total
        total += n
    
    def get_total():
        return total
    
    return {'add': add, 'total': get_total}

acc = make_accumulator()
acc['add'](10)
acc['add'](20)
acc['add'](30)
print(acc['total']())  # 60

练习 5:限流器(简化版) ​

python
import time

def make_rate_limiter(max_calls, period):
    calls = []
    
    def rate_limited(func):
        def wrapper(*args, **kwargs):
            nonlocal calls
            now = time.time()
            # 移除过期调用
            calls = [t for t in calls if now - t < period]
            
            if len(calls) >= max_calls:
                print(f"Rate limit exceeded: {max_calls} calls per {period}s")
                return None
            
            calls.append(now)
            return func(*args, **kwargs)
        return wrapper
    return rate_limited

@make_rate_limiter(3, 10)
def api_call():
    print("API called")
    return "Success"

# 测试
for i in range(5):
    api_call()

03-parameter-model ​

练习 1:可变参数求和 ​

python
def multiply_all(*numbers):
    if not numbers:
        return 1
    result = 1
    for num in numbers:
        result *= num
    return result

print(multiply_all())           # 1
print(multiply_all(2, 3, 4))    # 24

练习 2:字典合并 ​

python
def merge(**dicts):
    return dicts

d1 = merge(a=1, b=2)
d2 = merge(b=3, c=4)
print({**d1, **d2})  # {'a': 1, 'b': 3, 'c': 4}

# 或使用 *dicts
def merge(*dicts):
    result = {}
    for d in dicts:
        result.update(d)
    return result

print(merge({'a': 1}, {'b': 2}, {'c': 3}))  # {'a': 1, 'b': 2, 'c': 3}

练习 3:参数转发 ​

python
def log_calls(func):
    def wrapper(*args, **kwargs):
        print(f"Calling {func.__name__}")
        print(f"  args: {args}")
        print(f"  kwargs: {kwargs}")
        return func(*args, **kwargs)
    return wrapper

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

print(add(3, 5))
# Calling add
#   args: (3, 5)
#   kwargs: {}
# 8

练习 4:修复默认值陷阱 ​

python
def create_student(name, courses=None):
    if courses is None:
        courses = []
    courses.append("Math")
    return {'name': name, 'courses': courses}

alice = create_student("Alice")
bob = create_student("Bob")
print(alice)  # {'name': 'Alice', 'courses': ['Math']}
print(bob)    # {'name': 'Bob', 'courses': ['Math']}

练习 5:灵活的配置函数 ​

python
def configure(required_param, /, optional_param=10, *, flag=False, **extra):
    print(f"Required: {required_param}")
    print(f"Optional: {optional_param}")
    print(f"Flag: {flag}")
    print(f"Extra: {extra}")

configure(1)
# Required: 1
# Optional: 10
# Flag: False
# Extra: {}

configure(2, 20, flag=True, x=100, y=200)
# Required: 2
# Optional: 20
# Flag: True
# Extra: {'x': 100, 'y': 200}

# configure(required_param=3)  # TypeError: 仅限位置参数

本章完成 ​

完成这些练习后,你已经掌握了 Python 函数的核心机制:定义、作用域、闭包、参数模型。继续第三章学习对象、集合与文本数据。

回到第二章概览 · 返回Python 学习路线

用心记录每一步成长