my_func = outer_function("Hello from closure!") my_func() # Output: Hello from closure! # 此时 outer_function 已经执行完毕,但 my_func 仍然可以访问 msg
闭包是装饰器实现其功能的基础。
二、装饰器的基本语法与工作原理
2.1 装饰器的定义
装饰器函数通常接受一个函数作为参数,并返回一个新的函数(通常是内层包裹函数)。
1 2 3 4 5 6 7
defmy_decorator(func): # 装饰器函数,接受一个函数 func defwrapper(*args, **kwargs): # 包裹函数,会替代原函数执行 print("Something is happening before the function is called.") result = func(*args, **kwargs) # 调用原函数 print("Something is happening after the function is called.") return result return wrapper # 返回新的函数(wrapper)
defmy_decorator_with_wraps(func): @wraps(func) # 使用 wraps 装饰器 defwrapper(*args, **kwargs): print("Something is happening before the function is called.") result = func(*args, **kwargs) print("Something is happening after the function is called.") return result return wrapper
@my_decorator_with_wraps defgreet_with_name(name): """Greets the given name.""" print(f"Hello, {name}!")
print(greet_with_name.__name__) # Output: greet_with_name (而不是 wrapper) print(greet_with_name.__doc__) # Output: Greets the given name.
三、带参数的装饰器
有时候,我们需要在定义装饰器时传入参数,来控制装饰器的行为。这需要一层额外的函数嵌套。
3.1 定义带参数的装饰器
一个带参数的装饰器是一个工厂函数,它接收参数并返回一个真正的装饰器函数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
defrepeat(num_times): # 外部工厂函数,接收装饰器的参数 defdecorator(func): # 真正的装饰器函数,接收被装饰的函数 @wraps(func) defwrapper(*args, **kwargs): # 包裹函数 for _ inrange(num_times): result = func(*args, **kwargs) return result return wrapper return decorator # 工厂函数返回装饰器函数
def__call__(self, *args, **kwargs): print(f"Class decorator: Before calling {self.func.__name__}") result = self.func(*args, **kwargs) print(f"Class decorator: After calling {self.func.__name__}") return result
defdeco_a(func): @wraps(func) defwrapper(*args, **kwargs): print("------- Deco A Start -------") result = func(*args, **kwargs) print("------- Deco A End -------") return result return wrapper
defdeco_b(func): @wraps(func) defwrapper(*args, **kwargs): print("+++++++ Deco B Start +++++++") result = func(*args, **kwargs) print("+++++++ Deco B End +++++++") return result return wrapper
@deco_a @deco_b defmy_function(): print("This is the original function.")
my_function()
输出:
1 2 3 4 5
------- Deco A Start ------- +++++++ Deco B Start +++++++ This is the original function. +++++++ Deco B End +++++++ ------- Deco A End -------