首页 > 编程语言 >Python装饰器:深入探索功能增强的神奇工具(特点+应用+举例)

Python装饰器:深入探索功能增强的神奇工具(特点+应用+举例)

时间:2023-12-16 19:03:52浏览次数:35  
标签:return 函数 Python 举例 func time 装饰 def 神奇

Python装饰器是一项强大的特性,它允许程序员在不改变函数或类本身的情况下,增加、扩展或修改它们的行为。从日志记录到权限验证,再到性能分析和缓存,装饰器在Python编程中发挥着重要的作用。本文将深入探讨装饰器的各个方面,从基本概念到实际应用,带您领略装饰器的神奇之处。

装饰器是Python中一种强大且灵活的功能,它允许程序员在不修改函数或类本身的情况下,增加、扩展或修改它们的行为。装饰器本质上是一个可调用的对象,通常是一个函数或类,它接受一个函数作为参数,并返回一个新的函数或修改后的函数。它们主要用于AOP(面向切面编程),能够轻松地包装、修改或扩展函数或类的功能。

1. 基本语法

装饰器的基本语法是在函数或方法定义之前使用@符号,后面跟着装饰器函数的名称。装饰器函数接受要装饰的函数作为参数,并通常返回一个新的函数,通常在内部修改或扩展了原始函数的行为。基本语法如下:

def my_decorator(func):
    def wrapper(*args, **kwargs):
        # 在调用原始函数之前执行的操作
        result = func(*args, **kwargs)
        # 在调用原始函数之后执行的操作
        return result
    return wrapper

@my_decorator
def my_function():
    pass

2. 装饰器的特点

2.1. 函数作为参数:

装饰器本质上是一个函数,它接受一个函数作为参数,并返回一个新的函数或修改后的函数。这使得装饰器可以轻松地扩展或修改函数的行为。

2.2. 内部函数(闭包):

装饰器通常使用内部函数来实现,这种内部函数可以访问外部函数的变量。这种闭包结构使得装饰器能够在函数执行前后执行一些附加操作。

2.3. 语法简洁:

Python提供了@语法糖,使得应用装饰器更为直观和简洁。通过在函数或方法之前使用@decorator,可以明确指示该函数或方法要经过装饰器修饰。

2.4. 可复用性:

装饰器本身是可复用的。一个装饰器可以应用于多个函数或方法,提供了代码复用的便利性。

2.5. 动态性:

装饰器可以动态地应用于函数或类,这意味着在不修改原始函数定义的情况下,可以随时添加、删除或修改装饰器。

2.6. 应用广泛:

装饰器是实现AOP(面向切面编程)的重要工具,用于在不修改源代码的情况下,增加、扩展或修改函数或类的功能。它们可以用于日志记录、权限验证、性能分析、缓存等方面。

2.7. 类装饰器的灵活性:

除了函数装饰器外,Python还支持类装饰器。类装饰器通过实现__call__方法来实现装饰器的功能,使得装饰器行为更具灵活性和可扩展性。

3. 装饰器的应用

3.1. 日志记录

装饰器可以用于记录函数的调用信息,如函数名称、参数、执行时间等,方便调试和监控。

import functools
import time

def log_decorator(func):
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        start_time = time.time()
        result = func(*args, **kwargs)
        end_time = time.time()
        print(f"Function {func.__name__} executed in {end_time - start_time} seconds")
        return result
    return wrapper

@log_decorator
def my_function():
    # Function body
    pass

my_function()

这个示例展示了一个简单的日志记录器装饰器。log_decorator函数接收一个函数作为参数,然后返回一个修改后的函数。当调用my_function时,实际上是调用了log_decorator返回的wrapper函数,该函数记录了函数执行时间并打印出来。

3.2. 权限验证

装饰器可以用于验证用户的权限或登录状态,确保只有授权的用户才能执行某些函数或方法。

def login_required(func):
    def wrapper(*args, **kwargs):
        if user_logged_in():
            return func(*args, **kwargs)
        else:
            return "Login required to access this function"
    return wrapper

@login_required
def sensitive_operation():
    # Function body
    pass

result = sensitive_operation()

3.3. 性能分析

装饰器可以用于测量函数的执行时间以及资源使用情况,用于性能分析和优化。

import time

def performance_decorator(func):
    def wrapper(*args, **kwargs):
        start_time = time.time()
        result = func(*args, **kwargs)
        end_time = time.time()
        print(f"Function {func.__name__} executed in {end_time - start_time} seconds")
        return result
    return wrapper

@performance_decorator
def my_function():
    # Function body
    pass

my_function()

3.4. 缓存

装饰器可以用于实现简单的缓存功能,避免重复计算或获取数据。

import functools

def cache_decorator(func):
    cached_results = {}

    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        if args in cached_results:
            return cached_results[args]
        else:
            result = func(*args, **kwargs)
            cached_results[args] = result
            return result
    return wrapper

@cache_decorator
def expensive_operation(n):
    # Function body
    return n * n

result = expensive_operation(5)

3.5. 重试机制

装饰器可以用于在函数执行失败时自动重试,增加程序的健壮性。

import functools

def retry(times):
    def decorator_retry(func):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            for _ in range(times):
                try:
                    result = func(*args, **kwargs)
                    return result
                except Exception as e:
                    print(f"Exception: {e}. Retrying...")
        return wrapper
    return decorator_retry

@retry(times=3)
def unreliable_operation():
    # Function body that might fail
    pass

unreliable_operation()

这些是装饰器在实际应用中的几个示例。通过装饰器,可以在不修改原始函数代码的情况下,轻松地增强、扩展或修改函数的功能,使得代码更加模块化、可维护和灵活。

3.6. 参数化装饰器

def repeat(num_times):
    def decorator_repeat(func):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            for _ in range(num_times):
                result = func(*args, **kwargs)
            return result
        return wrapper
    return decorator_repeat

@repeat(num_times=3)
def greet(name):
    print(f"Hello, {name}!")

greet("Alice")

这个示例展示了一个可接受参数的装饰器。repeat函数用于创建一个重复调用函数的装饰器,该装饰器接受一个参数来确定函数重复执行的次数。

3.7. 类装饰器

class Timer:
    def __init__(self, func):
        self.func = func
        functools.update_wrapper(self, func)

    def __call__(self, *args, **kwargs):
        start_time = time.time()
        result = self.func(*args, **kwargs)
        end_time = time.time()
        print(f"Function {self.func.__name__} executed in {end_time - start_time} seconds")
        return result

@Timer
def my_function():
    # 模拟函数执行时间
    time.sleep(1)
    print("Function executed!")

my_function()

这个示例展示了一个基于类的装饰器。类装饰器是一个类,其__init__方法接收被装饰的函数,__call__方法定义了装饰器的行为。在这里,Timer类用于记录函数执行时间。

4. 结语

装饰器为Python编程带来了极大的灵活性和便利性。通过简洁的语法和强大的功能,它们使得代码更加模块化、可维护和灵活。从日常的日志记录到权限验证,再到性能分析和缓存,装饰器在各个领域都展现了其独特的价值。掌握装饰器的技巧将为您的代码增添更多的功能和魅力,期待您在实际开发中发挥装饰器的巨大潜力。


标签:return,函数,Python,举例,func,time,装饰,def,神奇
From: https://blog.51cto.com/u_16170163/8853385

相关文章

  • python高级之生成器
    生成器一、生成器与yield若函数体包含yield关键字,再调用函数,并不会执行函数体代码,得到的返回值即生成器对象defmy_range(start,stop,step=1):print('start...')whilestart<stop:yieldstartstart+=stepprint('end...')g=my_range(0,3)......
  • python爬虫
    #(2)importrequestsurl="https://www.google.cn/"foriinrange(20):try:r=requests.get(url,timeout=30)r.raise_for_status()r.encoding='utf-8'print(r.text)except:print('')......
  • Python准备之软件开发规范
    软件开发规范【一】常见的开发规范软件开发规范是一组为了保持代码质量、可维护性和协作效率而制定的约定和准则。这些规范通常由开发团队、组织或行业制定,并且在整个软件开发生命周期中都需要遵循。以下是一些常见的软件开发规范:命名规范:使用有意义的变量、函数和类名,遵循......
  • Python 潮流周刊第 31 期(摘要)
    本周刊由Python猫出品,精心筛选国内外的250+信息源,为你挑选最值得分享的文章、教程、开源项目、软件工具、播客和视频、热门话题等内容。愿景:帮助所有读者精进Python技术,并增长职业和副业的收入。周刊全文:https://pythoncat.top/posts/2023-12-16-weekly以下是本期摘要:......
  • 在linux环境上安装python
    一、环境操作系统:CentOS7.964位Python版本:3.8.2二、安装包:百度网盘地址及提取码:地址:https://pan.baidu.com/s/1P1kSAm_OuAiBZEShJi1XPA 提取码:88ra三、步骤:3.1上传安装包并解压缩mkdir-p/usr/local/python3cd/usr/local/python3tar-zxvfPython-3.8.2.tgz3.......
  • 【纯手工打造】时间戳转换工具(python)
    1.背景最近发现一个事情,如果日志中的时间戳,需要我们转换成时间,增加可读性。或者将时间转换成时间戳,来配置时间。相信大多人和我一样,都是打开网页,搜索在线时间戳转换工具,然后复制粘贴进去。个人认为可以手工打造一个python版本的时间戳转换工具,来解放双手,减少打开网页的时间,于是乎......
  • Python高级之模块导入
    模块导入与包的使用【一】模块与包概要模块(Module):定义:在Python中,模块是一个包含Python代码的文件。这些文件以.py为扩展名,可以包含变量、函数和类等,文件名为xxx.py,模块名则是xxx,导入模块可以引用模块中已经写好的功能。作用:模块提供了一种组织代码的方式,将相关的功......
  • Python学习之十五_不同类型数据库表内容比较
    Python学习只十五_不同类型数据库表内容比较前言最近学习力总结了很多Python相关的内容本次想继续学习一下不同数据库之间的数据比较.这样理论上可以极大的缩减不同数据库测试成本.感谢Python以及之前大拿的各种资料.这个学习还是表简单与单纯.理论上可以通过标准SQL......
  • Python学习之十六_virsh批量获取虚拟机IP地址的方法
    Python学习之十六_virsh批量获取虚拟机IP地址的方法Linux命令说明forjin\$(foriin`virshlist|grep-vId|greprunning|awk'{print$2}'`;\dovirshdumpxml$i|grep"macaddress"|awk-F\''{print$2}'&&e......
  • Python 以类作为装饰器 几种使用场景
    1.原函数、装饰器都没有参数代码:classTest:def__init__(self,func):print('Bein__init__process...')self.__func=funcdef__call__(self):print("...Startdecorate...")self.__func()prin......