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

深入理解 Python 的装饰器

💖 欢迎来到我的博客! 非常高兴能在这里与您相遇。在这里,您不仅能获得有趣的技术分享,还能感受到轻松愉快的氛围。无论您是编程新手,还是资深开发者,都能在这里找到属于您的知识宝藏,学习和成长。

🔍 博客内容包括:

  • Java核心技术与微服务:涵盖Java基础、JVM、并发编程、Redis、Kafka、Spring等,帮助您全面掌握企业级开发技术。
  • 大数据技术:涵盖Hadoop(HDFS)、Hive、Spark、Flink、Kafka、Redis、ECharts、Zookeeper等相关技术。
  • 开发工具:分享常用开发工具(IDEA、Git、Mac、Alfred、Typora等)的使用技巧,提升开发效率。
  • 数据库与优化:总结MySQL及其他常用数据库技术,解决实际工作中的数据库问题。
  • Python与大数据:专注于Python编程语言的深度学习,数据分析工具(如Pandas、NumPy)和大数据处理技术,帮助您掌握数据分析、数据挖掘、机器学习等技术。
  • 数据结构与算法:总结数据结构与算法的核心知识,提升编程思维,帮助您应对大厂面试挑战。

🌟 我的目标:持续学习与总结,分享技术心得与解决方案,和您一起探索技术的无限可能!在这里,我希望能与您共同进步,互相激励,成为更好的自己。

📣 欢迎订阅本专栏,与我一起在这个知识的海洋中不断学习、分享和成长!💻🚀


📍版权声明:本博客所有内容均为原创,遵循CC 4.0 BY-SA协议,转载请注明出处。

目录

一、什么是装饰器?

二、简单的装饰器示例

示例 1:打印日志

三、装饰器的原理

1. 函数即对象

2. 闭包

四、装饰器的高级用法

1. 为装饰器传递参数

2. 保留原函数的元数据

3. 装饰类方法

五、内置装饰器

1. @staticmethod

2. @classmethod

3. @property

六、多个装饰器的执行顺序

七、常见的装饰器应用场景

1. 权限验证

2. 性能分析


装饰器是 Python 中非常强大和灵活的功能。它可以在不改变函数定义的情况下,动态地为函数或方法添加新的功能。本文将带你深入理解装饰器的原理、用法以及一些高级技巧。


一、什么是装饰器?

装饰器本质上是一个函数,它接收一个函数作为参数,并返回一个增强后的函数。装饰器通常用来修改函数的行为,比如增加日志记录、访问控制或性能计时等。

装饰器的基本语法:

@decorator_function
def original_function():
    pass

 等价于:

def original_function():
    pass

original_function = decorator_function(original_function)

二、简单的装饰器示例

示例 1:打印日志
def logger(func):
    def wrapper(*args, **kwargs):
        print(f"Calling function '{func.__name__}' with arguments {args} and {kwargs}")
        result = func(*args, **kwargs)
        print(f"Function '{func.__name__}' returned {result}")
        return result
    return wrapper

@logger
def add(a, b):
    return a + b

add(3, 5)

输出:

Calling function 'add' with arguments (3, 5) and {}
Function 'add' returned 8

三、装饰器的原理

1. 函数即对象

在 Python 中,函数是一等公民,可以作为参数传递,也可以作为返回值。

2. 闭包

装饰器通常依赖闭包来保存上下文信息。闭包是指在嵌套函数中,内部函数引用了外部函数的变量。

示例:

def outer_function(message):
    def inner_function():
        print(message)
    return inner_function

closure = outer_function("Hello, World!")
closure()

输出:

Hello, World!

四、装饰器的高级用法

1. 为装饰器传递参数

如果需要给装饰器传递参数,可以使用多层嵌套。

示例:

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("Alice")

输出:

Hello, Alice!
Hello, Alice!
Hello, Alice!
2. 保留原函数的元数据

使用 functools.wraps 可以保留被装饰函数的原始信息(如名称和文档字符串)。

示例:

from functools import wraps

def logger(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        print(f"Calling {func.__name__}")
        return func(*args, **kwargs)
    return wrapper

@logger
def add(a, b):
    """Add two numbers."""
    return a + b

print(add.__name__)
print(add.__doc__)

输出:

add
Add two numbers.
3. 装饰类方法

装饰器也可以用于类方法。

示例:

def logger(func):
    def wrapper(*args, **kwargs):
        print(f"Calling {func.__name__}")
        return func(*args, **kwargs)
    return wrapper

class MyClass:
    @logger
    def greet(self):
        print("Hello from MyClass!")

obj = MyClass()
obj.greet()

输出:

Calling greet
Hello from MyClass!

五、内置装饰器

Python 提供了一些常用的内置装饰器:

1. @staticmethod

定义类的静态方法,与类实例无关。

class MyClass:
    @staticmethod
    def static_method():
        print("This is a static method.")

MyClass.static_method()
2. @classmethod

定义类方法,可以访问类本身。

class MyClass:
    @classmethod
    def class_method(cls):
        print(f"This is a class method from {cls}.")

MyClass.class_method()
3. @property

将方法变为属性。

class MyClass:
    def __init__(self, name):
        self._name = name

    @property
    def name(self):
        return self._name

obj = MyClass("Alice")
print(obj.name)

六、多个装饰器的执行顺序

当一个函数有多个装饰器时,它们的执行顺序是自下而上。

示例:

def decorator1(func):
    def wrapper(*args, **kwargs):
        print("Decorator 1")
        return func(*args, **kwargs)
    return wrapper

def decorator2(func):
    def wrapper(*args, **kwargs):
        print("Decorator 2")
        return func(*args, **kwargs)
    return wrapper

@decorator1
@decorator2
def greet():
    print("Hello!")

greet()

输出:

Decorator 1
Decorator 2
Hello!

七、常见的装饰器应用场景

1. 权限验证
def requires_permission(permission):
    def decorator(func):
        def wrapper(user, *args, **kwargs):
            if user.has_permission(permission):
                return func(user, *args, **kwargs)
            else:
                print("Permission denied!")
        return wrapper
    return decorator

@requires_permission("admin")
def delete_user(user, username):
    print(f"User {username} deleted.")
2. 性能分析
import time

def timer(func):
    def wrapper(*args, **kwargs):
        start = time.time()
        result = func(*args, **kwargs)
        end = time.time()
        print(f"{func.__name__} executed in {end - start:.2f} seconds")
        return result
    return wrapper

@timer
def compute():
    time.sleep(2)
    print("Computation done!")

compute()


http://www.kler.cn/a/503817.html

相关文章:

  • W25Q64-FLASH
  • ANSYS Fluent学习笔记(七)求解器四部分
  • SimpleFOC01|基于STM32F103+CubeMX,移植核心的common代码
  • 数据仓库基础常见面试题
  • 数据挖掘实训:天气数据分析与机器学习模型构建
  • BUUCTF:misc刷题记录4(会持续更新的)
  • Elasticsearch ES|QL 地理空间索引加入纽约犯罪地图
  • 计算机的错误计算(二百一十一)
  • 交互数字人:革新沟通的未来
  • Java Agent(三)、ASM 操作字节码入门
  • 【机器学习】神经网络训练技巧
  • 使用VSCode搭建Ruby on Rails集成开发环境
  • mac intel芯片下载安卓模拟器
  • 【css】浏览器强制设置元素状态(hover|focus……)
  • rclone,云存储备份和迁移的瑞士军刀,千字常文解析,附下载链接和安装操作步骤...
  • MAC AndroidStudio模拟器无网络
  • 新版懒人精灵基础老狼孩插件经典例子板块-视频教程
  • C# 内存篇
  • 《零基础Go语言算法实战》【题目 4-1】返回数组中所有元素的总和
  • 蓝牙BT04-A的使用与相关AT指令
  • AI大模型开发—1、百度的千帆大模型调用(文心一言的底层模型,ENRIE等系列)、API文档目的地
  • 多线程基础系列-多线程初识
  • kafka原理和实践
  • Linux:进程概念(二.查看进程、父进程与子进程、进程状态详解)
  • vscode的安装与使用
  • docker简单使用