当前位置: 首页 > news >正文

【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 中的高级功能,掌握它们不仅能使代码更具灵活性,还能减少重复代码,提高代码的可读性和维护性。


http://www.mrgr.cn/news/27930.html

相关文章:

  • 【eNSP】路由基础与路由来源——静态路由实验
  • 01 P2367 语文成绩
  • 使用Axios函数库进行网络请求的使用指南
  • World of Warcraft [WeakAuras]Barney Raid Kit - Collapsing Star Indicator
  • 关系型数据库和非关系型数据库详解
  • uniapp: 微信小程序包体积超过2M的优化方法
  • 光伏板热斑缺陷检测数据集
  • 浮点数在内存中的存储详解(超详细)
  • JavaScript高级——循环遍历加监听
  • PointNet++改进策略 :模块改进 | PointNetXt ,利用训练测量大幅提升PointNet模型性能
  • 如何迈向IT行业的成功之路
  • 智能机巢+无人机:自动化巡检技术详解
  • redisson实现分布式锁
  • 基于yolov5的混凝土缺陷检测系统python源码+onnx模型+评估指标曲线+精美GUI界面
  • 文章解读与仿真程序复现思路——电网技术EI\CSCD\北大核心《考虑生产环节内特性的工业负荷调峰优化运行及二次调频能力评估 》
  • 建筑裂缝检测图像ai模型训练数据集
  • 利用Python在Win10环境下实现拨号上网
  • PHP环境搭建
  • 解码 OpenAI 的 o1 系列大型语言模型
  • Linux查看自己公网IP
  • java 网络编程URL与URLConnection的使用
  • AIGC实战——多模态模型Flamingo
  • 使用EXPORT_SYMBOL
  • Python编程 - 异常处理与文件读写
  • 拒绝低效!开发者必备AI工具助你事半功倍!
  • Sitecore 定时任务使用介绍