函数嵌套与闭包机制详解
作用域与函数嵌套
在Python中,函数是独立的作用域单元。每个函数内部定义的变量仅在其自身及子作用域中有效。当执行函数时,会遵循"就近原则"查找变量:先在当前作用域内查找,若不存在则向上一级作用域逐层搜索。
name = "武沛齐"
def outer():
print(name)
outer() # 输出:武沛齐
嵌套函数的调用机制
函数本身也是作用域中的对象。当在一个函数中定义另一个函数时,内层函数可以访问外层函数的局部变量,形成闭包结构。
def execute():
print("开始")
def inner():
print("执行中")
inner()
print("结束")
execute()
作用域绑定时机
变量值的确定发生在函数被调用的时刻,而非定义时。这导致函数的行为可能受后续代码修改的影响。
def func():
print("你好")
func()
def execute():
print("开始")
func()
print("结束")
def func():
print(666)
execute() # 输出:666
函数嵌套的应用场景
虽然大多数函数应定义在全局作用域,但在需要封装私有逻辑且避免命名冲突时,可采用嵌套定义。
def generate_code():
def generate_chars():
import random
chars = 'abc123'
return ''.join(random.sample(chars, 4))
def draw_text(img):
from PIL import ImageDraw
draw = ImageDraw.Draw(img)
draw.text((10, 10), generate_chars(), fill='red')
img = Image.new('RGB', (120, 30), 'white')
draw_text(img)
img.save('code.png')
闭包的本质与实现
闭包是函数嵌套形成的特殊结构,它能将外部函数的局部状态"封存"于内部函数中,即使外部函数已退出,内部函数仍可访问该状态。
def create_counter(start=0):
count = start
def increment():
nonlocal count
count += 1
return count
return increment
counter1 = create_counter(5)
counter2 = create_counter(10)
print(counter1()) # 6
print(counter2()) # 11
print(counter1()) # 7
多线程任务分发示例
利用闭包为不同任务绑定参数,实现灵活的任务调度。
from concurrent.futures import ThreadPoolExecutor
def download_task(url, filename):
def worker():
import requests
response = requests.get(url)
with open(filename, 'wb') as f:
f.write(response.content)
return worker
executor = ThreadPoolExecutor(max_workers=3)
tasks = [
("https://example.com/file1.txt", "file1.txt"),
("https://example.com/file2.txt", "file2.txt"),
("https://example.com/file3.txt", "file3.txt")
]
for url, name in tasks:
executor.submit(download_task(url, name))
executor.shutdown()
装饰器的设计原理
装饰器是一种不修改原函数代码即可增强其功能的高级语法糖,核心基于闭包和高阶函数。
def timing_decorator(func):
import time
@functools.wraps(func)
def wrapper(*args, **kwargs):
start_time = time.time()
result = func(*args, **kwargs)
end_time = time.time()
print(f"{func.__name__} 执行耗时: {end_time - start_time:.4f}s")
return result
return wrapper
@timing_decorator
def slow_function():
import time
time.sleep(1)
return "完成"
slow_function()
装饰器的通用模板
标准写法应使用 `functools.wraps` 保持原函数元信息。
import functools
def my_decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
print("执行前操作")
result = func(*args, **kwargs)
print("执行后操作")
return result
return wrapper
实战练习
- 编写一个装饰器,在函数执行后输出 "after"
- 实现一个装饰器,使函数自动运行5次并返回结果列表
- 创建装饰器,确保文件路径目录存在再写入
- 分析以下代码输出结果:
def accumulator():
data = []
def add(value):
data.append(value)
print(data)
return add
add_func = accumulator()
add_func(10) # [10]
add_func(20) # [10, 20]
name = "武沛齐"
def outer():
name = "root"
def inner():
print(name)
inner()
outer() # root