引言
Python 的装饰器和闭包是两个强大而灵活的编程概念,它们能让你的代码更简洁、可读性更高,并且可以实现许多高级功能。
什么是闭包
闭包是指在一个内部函数中,引用了外部函数的变量。即使外部函数已经返回,内部函数依然可以访问这些变量。外部函数一般返回内部函数。
闭包示例
def outer(msg):
message = msg
def inner():
print(message)
return inner
# 创建一个闭包
closure = outer("Hello, World!")
closure() # 输出: Hello, World!
在这个例子中,inner 是一个闭包,它引用了 outer 的局部变量 message。
闭包的应用
闭包在许多场景下非常有用,比如可以用于创建工厂函数或者封装逻辑
def make_counter():
count = 0
def counter():
nonlocal count
count += 1
return count
return counter
counter = make_counter()
print(counter()) # 输出: 1
print(counter()) # 输出: 2
print(counter()) # 输出: 3
在这个例子中,counter 函数是一个闭包,它封装了 count 变量,并提供了增加 count 值的方法。内部函数counter,引用了外部函数的局部变量count,对于内部函数来说,外部函数的局部变量相当于缓存起来。
什么是装饰器
装饰器是一个函数,它接受另一个函数作为参数,并返回一个新函数。装饰器常用于在不改变原函数代码的情况下,扩展或修改函数的行为。
装饰器示例
def decorator(func):
def wrapper():
print("函数执行前")
func()
print("函数执行后")
return wrapper
@decorator
def hello():
print("Hello!")
hello()
在这个例子中,decorator 是一个装饰器,它在 hello 函数执行前后添加了一些额外的行为。
装饰器的应用
装饰器在实际应用中非常有用,可以用于日志记录、访问控制、性能计数、鉴权等场景,特别是在代码已完成,需要在后续补充一些辅助功能的时候,装饰器可以让我们不用大幅度改动已有代码的原有逻辑。以下是一个记录函数执行时间的装饰器示例:
import time
def timer(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
@timer
def slow():
time.sleep(2)
slow() # 输出: slow 执行时间 2.0012s
在这个例子中,timer 装饰器测量 slow 的执行时间并输出
使用带参数的装饰器
有时候我们需要使用创建带参数的装饰器,使用过flask的开发者应该比较清楚,设置函数路由时,需要传入一些参数,比如**@ns.route(‘/test’,endpoint=‘test_end’)**,我们可以通过再嵌套一层函数来实现
带参数的装饰器的示例
def repeat(n):
def decorator(func):
def wrapper(*args, **kwargs):
for _ in range(n):
func(*args, **kwargs)
return wrapper
return decorator
@repeat(3)
def greet(name):
print(f"Hello, {name}!")
greet("Lin") # 输出: Hello, lin! (共3次)
闭包和装饰器的结合
闭包和装饰器可以结合使用,实现更加复杂的功能。以下是一个计数函数调用次数的装饰器示例:
def counter(func):
count = 0
def wrapper(*args, **kwargs):
nonlocal count
count += 1
print(f"{func.__name__} 执行了 {count} 次")
return func(*args, **kwargs)
return wrapper
@counter
def hello():
print("Hello!")
hello() # 输出: hello 执行了 1 次
hello() # 输出: hello 执行了 2 次
在这个例子中,counter 装饰器使用闭包来记录函数的调用次数。
结论
Python 的装饰器和闭包是非常强大且灵活的工具,能够让你的代码更加简洁和高效。通过理解和应用这些概念,你可以在不修改原始代码的情况下扩展功能,并实现许多高级的编程模式。