【Python】Python装饰器介绍

本文详细解释了Python中的装饰器概念,包括闭包如何实现功能扩展,函数装饰器的原理与代码示例,以及类装饰器通过重写`__call__`方法的应用。通过实例演示了装饰器如何在不改变原函数结构的情况下增强其功能。
摘要由CSDN通过智能技术生成

一、什么是装饰器

  1. python装饰器是用于拓展原来函数功能的一种函数,
  2. 目的是在不改变原函数的情况下,给函数增加功能。
  3. 装饰器是通过闭包实现,所以讲装饰器首先得知道什么是闭包。

二、什么是闭包

一、什么是闭包

  1. 一个定义在函数内部的函数,闭包可以让变量脱离了该函数的作用域也依然能被访问到
  2. 定义一个嵌套函数,内函数内部使用外函数变量,让外函数将内函数当做参数返回,这样就组成了一个闭包

二、代码例子

def outer(x):   
    def inner():        
        y = x * 2        
        return y    
    return inner
    result=outer(10)
    print(result())

三、执行过程分析

  1. 调用外函数(outer),将参数赋值给x,此时x=10
  2. 执行外函数(outer),内函数(inner)不会被执行
  3. 执行到return语句此时返回内函数inner对象(不会被调用)
  4. 此时外函数(outer)执行结束的时候发现内部函数会用到自己的临时变量
  5. 此时外函数(outer)临时变量就不会释放,会绑定给内函数内函数(inner)继续使用
  6. 此时result得到的结果就是inner引用(对象),调用result就等于执行内函数(inner)

三、函数装饰器

一、原理

  1. 闭包的特性
  2. 函数可以被当做参数传递

二、代码例子

import timedef 
outer(fn):
    def inner(x,y):
        start_time = time.time()        
        result = fn(x,y)        
        end_time = time.time()        
        return result,end_time - start_time    
     print('第一次',inner)    
     return inner  
@outer
def test01(x,y):    
    time.sleep(5)    
    return x+y
print('第二次',test01)
result=test01(1,2)
print(result)

三、执行过程分析

第一步:执行到@outer相当于把函数 test01 赋值给 outer函数的fn参数
第二步:执行outer函数,返回inner函数
1、outer函数内部嵌套了一个inner函数,利用闭包的原理inner函数可以直接使用outer函数fn的参数
2、在执行outer函数的时候,inner函数并未被执行,是直接返回inner函数给test01函数
3、此时的test01函数已经被outer增加功能后返回的inner函数替换掉了(第一次,第二次打印结果就是证据)
第三步:执行test01(1,2),此时相当于执行inner(1,2)函数参数直接传递给inner函数的x,y
内存地址变化

  1. outer内存地址:<function outer at 0x102e051e0>
  2. test01内存地址:<function test01 at 0x103739158>
  3. inner内存地址:<function outer.<locals>.inner at 0x103739268>
  4. test01内存地址:<function outer.<locals>.inner at 0x103739268>

四、类装饰器

一、原理

  1. 通过重写call方法实现

二、代码例子

import time
class Decrator:    
    def __init__(self,fn):        
        self.fn = fn
        
    def __call__(self, *args, **kwargs):        
        start_time = time.time()        
        result = self.fn(*args, **kwargs)       
        end_time = time.time()        
        west_time = end_time - start_time        
        return result,west_time
@Decrator
def sum(x,y):    
    print(sum)    
    return x+y
sum(1,2)

三、执行过程分析

  1. __call__( ),方法的作用其实是把一个类的实例化对象变成了可调用对象,使得类实例对象可以像调用普通函数那样,以“对象名( )”的形式使用。

  2. 当调用sum函数的时候,会先将sum函数作为参数传给Decrator类(通过类的__init__初始化函数接收),此时 fn =sum(x,y)(只是实例未调用)

  3. 此时sum函数传递进来的参数为元组,就会赋值给了__call__方法,args

  4. 此时sum函数传递进来的参数为字典,就赋值给了__call__方法,kwargs

  5. __call__方法中做一系列操作之后,return self.fn(*args) 再传递给sum函数 *

  6. * __call__方法返回的函数self.fn(*args是被装饰后的函数实例,然后传给sum函数执行

  7. __call__必须要return装饰后的函数,否则会报错

作者:无糖气泡WU
链接:https://juejin.cn/post/7336155029936668713
来源:稀土掘金

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值