Python 核心 · #4 / 11
函数 + 作用域
可复用的逻辑与整洁的代码
为什么重要
函数让你的逻辑可复用、可测试、可读。
核心思想
函数是一个小程序:输入 → 处理 → 输出。默认参数把一个函数变成许多个;*args / **kwargs 让它能接受可变数量的参数。作用域遵循 LEGB 规则:Local(局部)→ Enclosing(闭包)→ Global(全局)→ Built-in(内置)。
试一试
默认参数 + 关键字参数:
def greet(name, greeting="Hello"):
return f"{greeting}, {name}!"
print(greet("Ada"))
print(greet("Linus", greeting="Hi"))
print(greet(greeting="Howdy", name="Margaret"))
*args / **kwargs 捕获多余的位置参数和关键字参数:
def describe(*things, **labels):
for t in things:
print("-", t)
for k, v in labels.items():
print(k, "=", v)
describe("apple", "banana", "cherry", colour="red", taste="sweet")
作用域:函数能看到外层的名字,但若不使用 nonlocal / global 就无法重新绑定它们:
counter = 0
def inc():
global counter
counter += 1
inc(); inc(); inc()
print("counter:", counter)
def outer():
x = 1
def inner():
nonlocal x
x += 10
inner()
print("outer.x:", x)
outer()
按数据类型划分的函数模式
函数的形态往往跟随它所处理的类型。下面这三种模式直接通向后面的数据结构课程:
- list → 返回一个新列表:
[x*2 for x in nums] - dict → 用
.get()来构建:counts[x] = counts.get(x, 0) + 1 - str → 先归一化,再比较:
s.lower()
快速检查
- 问:
print和return有什么区别? 答:return把一个值交回去;print只是显示出来。
小练习
- 写一个
is_even(n)。 - 用循环写一个
square_all(nums)。
该做与不该做
- 该做:保持函数短小且聚焦。
- 不该做:使用可变的默认参数,比如
def f(x=[])。
常见错误
- 错误: 忘记返回一个值。 修正: 加上
return。 - 错误: 修改了作为默认参数的列表。 修正: 用
None,并在函数内部创建列表。
关键要点
- 默认参数在定义时只求值一次——不要把可变对象用作默认值。
*args/**kwargs支持参数转发(f(*args, **kwargs))。- LEGB 作用域:Local → Enclosing → Global → Built-in。
- 纯函数(无副作用)更容易测试和推理。