装饰器的理解

首先函数是可以调用的对象:

import time
def new():
    print(time.time())
A = new
A()

如果有一个需求,保证new()不变的情况下,增加new()函数的功能,添加一行输出等等。

在函数运行期间动态增加功能的方式叫做装饰器decorator

从定义上理解decorator的满足要素:

  1. 首先不能动原函数
  2. 其次不能改原函数的调用方式,原来运行new()调用,增加了装饰器之后执行new()依然可以调用装饰后的函数

现有一个new()函数:

import time
def new():
    print(time.time())

new()

 

输出时间是格林尼治时间到现在的秒数,如果添加一个需求,当函数运行时输出时间,用我们熟悉的时间格式展示出来,

假定函数名称是  ti

直接将new函数当作参数传到ti里边是一种形式,但是这改变了函数new的调用方式,

如果使用new = ti(new),将ti(new)作为新的new再调用new,这样调用方式就没有改变,

但是调用new以后相当于new()--------> ti(new)()   这种形式,

这时候可以采用闭包的形式,在ti内部返回一个函数wrapper,执行wrapper可以返回new,

就变成new()-------------> ti(new)()  --------->  wrapper()

开始实践:

import time,datetime
def ti(func):
    def wrapper():
        print(datetime.datetime.now())
        return func()
    return wrapper



def new():
    print(time.time())

new = ti(new)

new()

 

new = ti(new)可以用更简洁的方式:

@ti

@ti放在new函数上一行,它作用于new()函数,等同于new = ti(new)

一个简单的装饰器就出来了。

 

如果new函数需要参数怎么办?

new传入参数,在调用方式不变的情况下,就是变更之后的new传入参数,相当于给ti(new)传入参数,相当于wrapper传入参数,

import time,datetime

def ti(func):
    def wrapper(*args,**kwargs):
        print('now: %s'%datetime.datetime.now())
        return func(*args,**kwargs)
    return wrapper



@ti
def new(sec=''):
    print(time.time(),sec)

new('seconds')

解决传入参数。

 

此时执行

print(new.__name__)

输出结果:

wrapper

本来的new已经变成了wrapper,不行,原来的是new,不能变

functools模块可以做到(functools可以把原始的new的__name__属性复制到wrapper中,否则有些依赖函数签名的代码执行会出错。)

@functools.wraps(func)

他要修改wrapper,所以放在wrapper上边,等同于

wrapper = functools.wraps(func)(wrapper)

import functools,time,datetime

def ti(func):
    @functools.wraps(func)
    def wrapper(*args,**kwargs):
        print('now: %s'%datetime.datetime.now())
        return func(*args,**kwargs)
    return wrapper


@ti
def new(sec=''):
    print(time.time(),sec)


new('seconds')

 

这时候的print(new.__name__)

输出就会显示new了,解决。

 

hold on

如果ti需要传入参数呢。。。

ti传入参数的位置只能在@ti处,那是在ti函数外唯一一次可以传入参数的机会,传入的形式只能是@ti('canshu')

先分析这个形式的意思,@ti后边跟的是 ('canshu') ,然后再是new()函数,也就是new = ti('canshu')(new)

如果在ti外部再加一层函数newti,它包含参数('canshu'),然后返回一个ti函数,ti执行的时候传入new,后边就不用变了

如下:

import functools,time,datetime

def newti(text):
    def ti(func):
        @functools.wraps(func)
        def wrapper(*args,**kwargs):
            print('now: %s\n%s'%(datetime.datetime.now(),text))
            return func(*args,**kwargs)
        return wrapper
    return ti


@newti('end')
def new(sec=''):
    print(time.time(),sec)


new('seconds')

解决。

暂时理解到这里。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值