首页 > 编程语言 >Python - Decorators

Python - Decorators

时间:2024-07-31 15:17:38浏览次数:13  
标签:function Python def wrapper decorator kwargs Decorators fn

A decorator is a callable that takes a callable as input and returns a callable. This is the general definition of a decorator. The callable in this definition can be a function or a class. In our initial discussion, we will talk about decorator functions that are used to decorate functions; we will talk about classes later on. So, for the time being, we can think of a decorator as a function that takes a function as input and returns a function.

Decorators are used to add some functionality to a function. They allow you to execute some extra code before or after the execution of a function. This extra work is done without making any changes to the source code of the function. So, by using a decorator we can extend the behavior of a function without actually modifying its code.

A decorator is a function that takes another function as an argument, decorates it with the extra functionality and gives you a decorated function as the result.

def func1():
    print('Hello world')
    print('Welcome to Python')

def my_decorator(fn):
    def wrapper():
        print('Hi … Starting execution')
        fn()
        print('Bye … finished executing\n')
    return wrapper

decorated_func1 = my_decorator(func1)

 

@my_decorator
def func3():
   print('Learning decorators')

The function func3 is decorated using the automated decoration syntax and so now we do not need to write the statement func3 = my_decorator(func3). The @ syntax automates this reassignment of the function name.

 

Decorator Example: Checking return values

Decorator Example: Checking argument values

 

Preserving metadata of a function after decoration

If we do not want the original function to lose its name, documentation and other attributes, even after decoration, then we can use the wraps function from the functools module. This wraps function is a decorator that copies the introspection details of a function to another function. We will apply this decorator to the wrapper function.

from functools import wraps

def trace(fn):
    @wraps(fn)
    def wrapper(*args, **kwargs):
        print(f'{fn.__name__} called')
        print(f'args : {args}  kwargs : {kwargs}' )
        result = fn(*args, **kwargs)
        print(f'Return value : {result}\n')      
        return result

    return wrapper

This wraps decorator is little different, it is a decorator that takes an argument. We will see such decorators in the next section. We send function fn as argument to this wrapper function. So now all the important metadata of fn will be copied in the wrapper function.

 

General template for writing a decorator

from functools import wraps

def decorator_name(fn):
     @wraps(fn)
     def wrapper(*args, **kwargs):
        #Place code that has to be executed before function call 
        result = fn(*args, **kwargs)
        #Place code that has to be executed after function call 
        return result

     return wrapper

 

General template for writing a decorator factory

from functools import wraps

def decorator_name(parameter1, parameter2, …):
   def actual_decorator(fn):
     @wraps(fn)
     def wrapper(*args, **kwargs):
        #Place code that has to be executed before function call 
        result = fn(*args, **kwargs)
        #Place code that has to be executed after function call 
        return result

      return wrapper

   return actual_decorator

 

Applying decorators to imported functions

We can even apply our own decorators to the functions that we import from standard library or third-party packages. However, we cannot use the @ syntax for these functions.

from math import factorial
from random import randint


def trace(fn):
    def wrapper(*args, **kwargs):
        print(f'{fn.__name__} called')
        print(f'args : {args}  kwargs : {kwargs}' )
        result = fn(*args, **kwargs)
        print(f'Return value : {result}\n')      

        return result

    return wrapper


factorial = trace(factorial)
randint = trace(randint)
factorial(3)
randint(5, 50)

 

标签:function,Python,def,wrapper,decorator,kwargs,Decorators,fn
From: https://www.cnblogs.com/zhangzhihui/p/18334725

相关文章

  • Python捕获一组中的1000个项目进行处理
    我有一个包含数千条记录的大表(可能有3,000到75,000条记录),我将所有数字ID放入排序列表中。我想一次有序地处理一组1000个ID。我如何优雅地获取前1000个和“标签”,设置为“223344到337788”(字典在这里有意义吗,或者只是列表捕获中的第一个/最后一个项目......以跟......
  • 在 Python 中创建和/或检查编号变量的优雅方法
    我是一个试图学习Python的老家伙,所以我最后的编码经验是使用BASIC-不,不是VisualBasic。我理解一些与Python相关的概念,但我处于初级编码阶段,所以我使用“强力”逻辑编写了这个项目-基本上,将字符串分解为单个字母,然后用经典的“”测试每个字母猜单词类型的游戏。......
  • 使用法兰克福 API 和 Python 虚拟环境时出现 404 错误
    我正在VisualStudioCode中用Python制作货币转换器脚本,并且使用法兰克福API,它在几天前一直工作正常,直到现在每次我尝试获取API时都会收到404错误:|||输出:>response=requests.get(f"https://api.frankfurter.app/latest?amount={amount}&from={CF}&to={CT}")>......
  • 我的目标是检测车道并控制车辆保持在车道中央。使用Python
    我目前正在做一个项目,我是一个初学者。并且我需要找到一种方法来使用检测到的车道来控制我的项目车辆保持在两条线之间的中心。img1|||img2我有疑问的话题如下如何判断我的机器人车是否在车道中央?我们应该用什么方法来控制机器人的转向......
  • 【学习笔记】Matlab和python双语言的学习(主成分分析法)
    文章目录前言一、主成分分析法1.主成分分析法简介2.主成分分析法原理3.主成分分析法思想4.PCA的计算步骤二、代码实现----Matlab三、代码实现----python总结前言通过模型算法,熟练对Matlab和python的应用。学习视频链接:https://www.bilibili.com/video/BV1EK41187......
  • 如何使用python输入提示具有相同参数类型但不同返回类型的函数?
    我有一个函数,它的返回类型是tuple[bool,set[int]|str]如果第0项是True,则第1项是结果set[int],否则第1项是一个str,显示失败的原因。是这样的defcallee(para_a:int)->tuple[bool,set[int]|str]:result=set([1,2,3])if......
  • 彻底卸载Python
        前言通常我们在一些软件的使用上有碰壁,第一反应就是卸载重装。所以有小伙伴就问我Python怎么卸载才能彻底卸载干净,今天这篇文章,小编就来教大家如何彻底卸载Python 软件卸载方法1:首先,在安装python时,下载了一个可执行文件,也就是Python的安装包,我们双击它,点击uninstal......
  • 如何使用 Azure Devops API (Python) 提取特定提交的文件内容?
    这就是我想要做的:每次对我的存储库中的特定分支进行提交时,我想提取该提交中更改的所有YAML文件,对其内容进行一些修改,然后将结果作为PR推送到一个新的、独立的分支。我已经弄清楚了这里的大部分步骤,但我陷入了解析提交文件内容部分。我已经尝试过get_item_content和......
  • 在Python中,为什么这个负浮点数能够通过非负while循环测试条件?
    在Python中工作收集用户输入输入需要非负在程序的另一部分成功使用了While条件但现在不明白为什么这个捕获有效输入的测试失败了。print("Howmanygramsofxyzarerequired?")xyz_string=input()xyz=int(float(xyz_string))whilex......
  • 【Python】正色表达式 - 验证罗马数字
    一、题目Youaregivenastring,andyouhavetovalidatewhetherit'savalidRomannumeral.Ifitisvalid,printTrue.Otherwise,printFalse.TraytocreatearegularexpressionforavalidRomannumeral.InputFormatAsinglelineofinputcontainin......