python装饰器详细解析

python3装饰器详细解析

python3装饰器(fuctional decorators)就是用于拓展原来函数功能的一种函数,目的在于不爱变原来函数名的情况下该函数添加新功能的方法。

一般而言,我们想要拓展原来的函数代码,最直接的方法就是进入代码里修改,例如:

import time
  5 def f():
  6     for i in range(10):
  7         if i<=5:
  8             print(i)
  9             time.sleep(1)
 10             i+=1
 11         else:
 12             print(i)
 13             
 14 
 15 if __name__=='__main__':
 16     f()

这是最原始的函数,现在想要记录下这个函数运行的总时间,最简单的方法就是改动原来的代码:

import time
 20 def f():
 21     start=time.time()
 22     for i in range(10):
 23         if i <=5:
 24             print(i)
 25             time.sleep(1)
 26             i+=1
 27         else:
 28             print(i)
 29     end=time.time()
 30     execute_time=end-start
 31     print('time is %d ms'%execute_time)
 32 
 33 if __name__=='__main__':
 34 
 35     f()

但是实际上有些核心代码在开发过程中不能直接更改,所以在不更改原来代码的情况下,我们可以在定义一个函数,在执行过程中需要再次 执行该函数

 import time
 41 
 42 def deco(f):
 43 
 44     def cost_time():
 45         start=time.time()
 46         f()
 47         end=time.time()
 48         execute_time=end-start
 49         print('time is %d ms'% execute_time)
 50     return cost_time
 51 
 52 @deco
 53 def f():
 54     for i in range(10):
 55         if i<=5:
 56             print(i)
 57             time.sleep(1)
 58             i+=1
 59         else:
 60             print(i)
 61 
 62 if __name__=="__main__":
 63     f()

这里我们定义一个函数deco,参数为一个函数,返回值也是一个函数,其中作为参数的这个函数f()就在返回函数cost_time()的内部执行,然后在函数f()前面加上一个@deco,f()就相当于被加入了计时功能,现在只需要调用f(),他就已经变为‘新的更多功能’的函数了。(不需要重复执行原函数)

扩展1:带有固定参数的装饰器

import time
 69 def deco(f):
 70     def add_sum(a,b):
 71         start=time.time()
 72         f(a,b)
 73         end=time.time()
 74         cost_time=(end-start)*1000
 75         print('time is %d ms'% cost_time)
 76     return add_sum
 77 
 78 @deco
 79 def f(a,b):
 80     print('start')
 81     time.sleep(1)
 82     print('result is %d'% (a+b))
 83 
 84 
 85 if __name__=='__main__':
 86     f(3,4)

扩展2:无固定参数的装饰器

import time
 94 def deco(f):
 95     def cost_time(*args,**kwargs):
 96         start=time.time()
 97         f(*args,**kwargs)
 98         end=time.time()
 99         cost_time=(end-start)*1000
100         print('cost time %d ms'% cost_time)
101     return cost_time
102 
103 @deco
104 
105 def f(a,b,c):
106     print('start')
107     time.sleep(1)
108     print('sum=%d'%(a+b+c))
109 
110 if __name__=='__main__':
111     f(3,4,5)

扩展3:基于类的装饰器
前面我们一直讨论装饰器修饰的都是一个函数,其实也可以定义基于类的装饰器。

class Bold(object):
    def __init__(self,f):
        self.f=f
    def __call__(self, *args, **kwargs):
        return "<b>"+ self.f(*args,**kwargs)+'</b>'

@Bold
def f():
    return 'hello world'

if __name__=='__main__':
    print(f())
__init__():用于初始化一个实例对象,它接受一个函数作为参数,也就是被装饰的函数
__call__():让一个实例对象可调用,就像函数调用一样,在调用被装饰函数时别调用

扩展4: 带参数的类装饰器

class Tag(object):
    def __init__(self,tag):
        self.tag=tag
    def __call__(self, f):
        def prapped(*args,**wargs):
            return '<{tag}>{res}</{tag}>'.format(tag=self.tag,res=f(*args,**wargs))
        return prapped

@Tag('b')
def f():
    return 'hello world'

if __name__=='__main__':
    print(f())

装饰器的调用顺序

装饰器是可以叠加使用的,在python中装饰器的调用顺序是与定义顺序相反的

python内置装饰器

在python中有三个内置装饰器,都是跟class相关的:staticmethod、classmethod和property

  • staticmethod 是类静态方法,跟成员方法的区别是没有self参数,并且可以在不进行实例化的情况下调用
  • classmethod 与成员方法的区别在于所接受的第一个参数不是self(类指针实例),而是cls(当前的具体类型)
  • property 是属性的意思,表示可以通过类实例直接访问的信息
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值