您的位置:首页 > 财经 > 产业 > 【30天玩转python】装饰器与闭包

【30天玩转python】装饰器与闭包

2024/11/17 2:41:11 来源:https://blog.csdn.net/weixin_39372311/article/details/142244020  浏览:    关键词:【30天玩转python】装饰器与闭包

装饰器与闭包

装饰器和闭包是 Python 中非常强大的特性。理解它们不仅有助于写出更简洁和模块化的代码,还能极大地提高代码的复用性和灵活性。本节将详细介绍装饰器与闭包的概念、用法及其在实际编程中的应用。


1. 闭包

闭包(Closure)是指一个函数在其作用域之外调用时,依然能够访问其作用域内的变量。闭包函数可以捕获并保存外部函数中的局部变量,即使外部函数已经返回,这些变量依然能够被访问。

1.1 闭包的定义

要形成闭包,需要满足以下条件:

  1. 必须有一个嵌套函数(即函数内部定义了另一个函数)。
  2. 嵌套函数必须引用外部函数中的变量。
  3. 外部函数的返回值是嵌套函数。
1.2 示例
def outer_func(msg):def inner_func():print(msg)  # 引用了外部函数的变量return inner_funcclosure = outer_func("Hello, Closure!")
closure()  # 输出:Hello, Closure!

在上面的例子中,inner_func() 是一个闭包,因为它访问了 outer_func() 的局部变量 msg,即使 outer_func() 已经返回。

1.3 闭包的应用

闭包可以用于保存状态或对某些参数进行预先配置。它经常用于工厂模式或装饰器中。

计数器闭包:

def make_counter():count = 0def counter():nonlocal count  # 声明count是外部函数的变量count += 1return countreturn countercounter_a = make_counter()
print(counter_a())  # 输出:1
print(counter_a())  # 输出:2counter_b = make_counter()
print(counter_b())  # 输出:1

2. 装饰器

装饰器(Decorator)是一个可以改变其他函数行为的函数。它允许在不修改原函数代码的情况下,向原函数添加新的功能。这使得代码更加灵活和可复用。

2.1 装饰器的定义

装饰器本质上是一个接受函数作为参数的函数,通常返回一个包装函数。这个包装函数会在原函数执行前或执行后添加额外的逻辑。

def decorator_func(func):def wrapper():print("在执行函数之前")func()  # 调用原函数print("在执行函数之后")return wrapper@decorator_func  # 使用装饰器
def say_hello():print("Hello!")say_hello()
# 输出:
# 在执行函数之前
# Hello!
# 在执行函数之后

在这个例子中,@decorator_func 是装饰器语法糖,它等价于 say_hello = decorator_func(say_hello)

2.2 带参数的装饰器

装饰器可以处理带有参数的函数。为了做到这一点,我们需要在包装函数中接受参数并传递给原函数。

def decorator_func(func):def wrapper(*args, **kwargs):  # 接受任意参数print("在执行函数之前")result = func(*args, **kwargs)print("在执行函数之后")return resultreturn wrapper@decorator_func
def add(a, b):return a + bprint(add(2, 3))  # 输出:在执行函数之前 5 在执行函数之后
2.3 带参数的装饰器(装饰器工厂)

如果需要让装饰器自身接受参数,我们需要使用一个多层嵌套的函数,即装饰器工厂。

def decorator_with_args(msg):def decorator_func(func):def wrapper(*args, **kwargs):print(f"Message: {msg}")return func(*args, **kwargs)return wrapperreturn decorator_func@decorator_with_args("装饰器参数")
def greet(name):print(f"Hello, {name}!")greet("Alice")
# 输出:
# Message: 装饰器参数
# Hello, Alice!

3. 装饰器的实际应用

装饰器在实际编程中非常有用,尤其是在需要为多个函数添加相同的功能时。以下是一些常见的应用场景。

3.1 记录函数执行时间

通过装饰器来记录函数的执行时间,这在性能调优时非常有用。

import timedef 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} 秒")return resultreturn wrapper@timer
def slow_function():time.sleep(2)slow_function()
# 输出:slow_function 执行时间: 2.0001 秒
3.2 权限校验

装饰器可以用于实现权限校验,比如在某些 API 接口中,只允许授权用户访问。

def requires_permission(func):def wrapper(user):if user.get('is_admin'):return func(user)else:print("无权限访问")return wrapper@requires_permission
def access_admin_panel(user):print("访问管理后台")user = {"username": "alice", "is_admin": True}
access_admin_panel(user)  # 输出:访问管理后台user = {"username": "bob", "is_admin": False}
access_admin_panel(user)  # 输出:无权限访问
3.3 缓存(Memoization)

装饰器可以用于缓存函数的计算结果,从而避免重复计算。这在处理递归函数时尤其有用,比如计算斐波那契数列。

def memoize(func):cache = {}def wrapper(n):if n not in cache:cache[n] = func(n)return cache[n]return wrapper@memoize
def fibonacci(n):if n <= 1:return nreturn fibonacci(n-1) + fibonacci(n-2)print(fibonacci(10))  # 输出:55

4. 小结

  • 闭包:允许嵌套函数记住并访问外部函数的变量,哪怕外部函数已经返回。常用于保持状态或函数工厂。
  • 装饰器:是一种能够在不改变函数本身的情况下扩展其功能的工具,非常适合代码复用和功能增强。

装饰器与闭包都是 Python 中的高级功能,掌握它们不仅能使代码更具灵活性,还能减少重复代码,提高代码的可读性和维护性。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com