Python3入门指南Python语言的特点和实际应用Python3环境搭建配置VSCode进行Python开发Python基础语法Python变量与数据类型Python数据类型转换Python解释器使用Python注释使用Python运算符Python数字类型Python字符串操作Python列表操作Python元组使用Python字典使用Python集合使用Python条件控制详解Python循环语句详解Python编程入门实践Python推导式详解Python迭代器和生成器Python with语句详解Python函数详解Python lambda(匿名函数)Python装饰器Python数据结构Python模块和包使用Python中__name__和__main__的用法Python输入输出:从基础到文件操作Python文件操作Python OS模块使用Python错误和异常处理Python面向对象编程Python命名空间和作用域Python虚拟环境:venv详细教程Python类型注解Python标准库常用模块Python正则表达式Python CGI编程Python MySQL(mysql-connector驱动)Python MySQL(PyMySQL驱动)Python网络编程Python发送邮件Python多线程编程Python XML解析Python JSON解析Python日期和时间处理Python操作MongoDBPython urllib库使用Python uWSGI 安装与配置Python pip包管理工具Python operator模块Python math模块Python requests模块HTTP请求Python random模块Python OpenAI库Python AI绘画制作Python statistics模块Python hashlib模块:哈希加密Python量化交易Python pyecharts数据可视化Python Selenium网页自动化Python BeautifulSoup网页数据提取Python Scrapy爬虫框架Python Markdown转HTMLPython sys模块Python Pickle模块:数据存储Python subprocess模块Python queue队列模块Python StringIO内存文件操作Python logging日志记录Python datetime日期时间处理Python re正则表达式Python csv表格数据处理Python threading 多线程编程Python asyncio 异步编程Python PyQt 图形界面开发Python 应用方向和常用库框架

Python装饰器

装饰器是Python中一个很有用的特性,它能够在不改变原有代码的情况下,给函数或类添加新的功能。这个功能让代码更加灵活,也更容易维护。


什么是装饰器?

装饰器本质上是一个函数,它接受另一个函数作为参数,然后返回一个新的函数。使用装饰器可以在不修改原函数代码的情况下,为函数添加额外的功能。

在Python中,我们使用@符号来应用装饰器。Python本身也提供了一些内置的装饰器,比如@staticmethod和@classmethod。


装饰器能做什么?

装饰器在实际开发中有很多用途:

  • 记录日志:记录函数的调用信息、参数和返回值

  • 性能测试:测量函数的执行时间

  • 权限检查:控制对某些函数的访问权限

  • 结果缓存:存储函数计算结果,提高运行速度

  • 错误重试:在函数失败时自动重试


装饰器的基本用法

最简单的装饰器

我们先来看一个基本的装饰器结构:

def decorator_function(original_function):
    def wrapper(*args, **kwargs):
        # 在调用原函数前执行的代码
        print("函数调用开始")
        
        result = original_function(*args, **kwargs)
        
        # 在调用原函数后执行的代码
        print("函数调用结束")
        
        return result
    return wrapper

# 使用装饰器
@decorator_function
def target_function(arg1, arg2):
    print(f"执行函数,参数:{arg1}, {arg2}")

# 测试
target_function("hello", "world")

运行结果:

函数调用开始
执行函数,参数:hello, world
函数调用结束

装饰器的工作原理

当我们使用@decorator_function时,实际上相当于执行了:

def target_function(arg1, arg2):
    print(f"执行函数,参数:{arg1}, {arg2}")

target_function = decorator_function(target_function)

原来的target_function被替换成了decorator_function(target_function)返回的wrapper函数。


实际应用示例

记录执行时间的装饰器

import time

def timer_decorator(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 result
    return wrapper

@timer_decorator
def slow_function():
    time.sleep(1)
    print("函数执行完毕")

slow_function()

带参数的函数装饰器

如果原函数需要参数,装饰器需要这样写:

def my_decorator(func):
    def wrapper(*args, **kwargs):
        print("准备执行函数")
        result = func(*args, **kwargs)
        print("函数执行完成")
        return result
    return wrapper

@my_decorator
def greet(name, age):
    print(f"你好,{name},今年{age}岁")

greet("小明", 20)


带参数的装饰器

有时候我们需要让装饰器本身也能接受参数:

def repeat(num_times):
    def decorator(func):
        def wrapper(*args, **kwargs):
            for i in range(num_times):
                print(f"第{i+1}次执行:")
                result = func(*args, **kwargs)
            return result
        return wrapper
    return decorator

@repeat(3)
def say_hello():
    print("Hello!")

say_hello()

运行结果:

第1次执行:
Hello!
第2次执行:
Hello!
第3次执行:
Hello!

这个例子中,repeat是一个装饰器工厂函数,它返回真正的装饰器。


类装饰器

除了函数装饰器,Python还支持类装饰器。类装饰器可以修改类的行为。

函数形式的类装饰器

def add_method(cls):
    def new_method(self):
        return "这是新增的方法"
    
    cls.new_method = new_method
    return cls

@add_method
class MyClass:
    def original_method(self):
        return "这是原始方法"

obj = MyClass()
print(obj.original_method())  # 这是原始方法
print(obj.new_method())       # 这是新增的方法

实现单例模式的类装饰器

class SingletonDecorator:
    def __init__(self, cls):
        self.cls = cls
        self.instance = None
    
    def __call__(self, *args, **kwargs):
        if self.instance is None:
            self.instance = self.cls(*args, **kwargs)
        return self.instance

@SingletonDecorator
class Database:
    def __init__(self):
        print("数据库连接已创建")

# 测试
db1 = Database()
db2 = Database()
print(db1 is db2)  # 输出:True


Python内置装饰器

Python提供了几个有用的内置装饰器:

@staticmethod

静态方法,不需要访问类或实例的数据:

class MathUtils:
    @staticmethod
    def add(x, y):
        return x + y

# 直接通过类调用,不需要创建实例
result = MathUtils.add(5, 3)
print(result)  # 输出:8

@classmethod

类方法,第一个参数是类本身:

class Person:
    count = 0
    
    def __init__(self, name):
        self.name = name
        Person.count += 1
    
    @classmethod
    def get_count(cls):
        return cls.count

person1 = Person("小明")
person2 = Person("小红")
print(Person.get_count())  # 输出:2

@property

将方法转换为属性:

class Circle:
    def __init__(self, radius):
        self._radius = radius
    
    @property
    def radius(self):
        return self._radius
    
    @radius.setter
    def radius(self, value):
        if value <= 0:
            raise ValueError("半径必须大于0")
        self._radius = value
    
    @property
    def area(self):
        return 3.14159 * self._radius ** 2

circle = Circle(5)
print(circle.area)  # 输出:78.53975
circle.radius = 10
print(circle.area)  # 输出:314.159


多个装饰器的使用

可以同时使用多个装饰器,它们会从下往上依次执行:

def decorator1(func):
    def wrapper():
        print("装饰器1 - 前")
        func()
        print("装饰器1 - 后")
    return wrapper

def decorator2(func):
    def wrapper():
        print("装饰器2 - 前")
        func()
        print("装饰器2 - 后")
    return wrapper

@decorator1
@decorator2
def my_function():
    print("原始函数")

my_function()

运行结果:

装饰器1 - 前
装饰器2 - 前
原始函数
装饰器2 - 后
装饰器1 - 后


实用的装饰器示例

缓存装饰器

def cache_decorator(func):
    cache = {}
    def wrapper(*args):
        if args in cache:
            print("从缓存中获取结果")
            return cache[args]
        result = func(*args)
        cache[args] = result
        print("计算结果并缓存")
        return result
    return wrapper

@cache_decorator
def expensive_calculation(x):
    return x * x

print(expensive_calculation(5))  # 计算结果并缓存 \n 25
print(expensive_calculation(5))  # 从缓存中获取结果 \n 25

权限检查装饰器

def login_required(func):
    def wrapper(user, *args, **kwargs):
        if not user.get('is_login', False):
            print("请先登录")
            return None
        return func(user, *args, **kwargs)
    return wrapper

@login_required
def view_profile(user):
    print(f"显示用户资料:{user['name']}")

# 测试
user1 = {'name': '小明', 'is_login': True}
user2 = {'name': '小红', 'is_login': False}

view_profile(user1)  # 显示用户资料:小明
view_profile(user2)  # 请先登录

错误重试装饰器

import time

def retry(max_attempts=3, delay=1):
    def decorator(func):
        def wrapper(*args, **kwargs):
            for attempt in range(max_attempts):
                try:
                    return func(*args, **kwargs)
                except Exception as e:
                    if attempt == max_attempts - 1:
                        raise e
                    print(f"第{attempt + 1}次尝试失败,{delay}秒后重试")
                    time.sleep(delay)
            return None
        return wrapper
    return decorator

@retry(max_attempts=3, delay=2)
def unstable_operation():
    import random
    if random.random() < 0.7:
        raise Exception("操作失败")
    return "操作成功"

result = unstable_operation()
print(result)


使用装饰器的注意事项

  1. 保留原函数信息:使用functools.wraps保留原函数的元信息

import functools

def my_decorator(func):
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        print("装饰器功能")
        return func(*args, **kwargs)
    return wrapper
  1. 调试装饰器:装饰器可能会让错误信息更难理解,要注意调试

  2. 性能考虑:装饰器会增加函数调用开销,在性能敏感的场景要谨慎使用


总结

装饰器是Python中强大的功能,它让我们能够:

  • 在不修改原代码的情况下添加功能

  • 保持代码的整洁和可读性

  • 实现通用的功能,如日志、缓存、权限检查等

  • 通过组合不同的装饰器来构建复杂的功能

掌握装饰器的使用,能够让你的Python代码更加专业和强大。从简单的函数装饰器到复杂的类装饰器,这个功能在实际开发中有着广泛的应用。

记住,装饰器虽然强大,但也不要过度使用。在合适的场景使用合适的装饰器,才能让代码既强大又易于维护。

本文内容仅供个人学习/研究/参考使用,不构成任何决策建议或专业指导。分享/转载时请标明原文来源,同时请勿将内容用于商业售卖、虚假宣传等非学习用途哦~感谢您的理解与支持!

链接: https://fly63.com/course/36_2096

目录选择