装饰器

装饰器

@func1
def func():
    print('aaa')

装饰器存在的意义

  • 不影响原有函数的功能
  • 可以添加新功能

一般常见的,比如拿到第三方的API接口,第三方不允许修改这个接口。这个时候,装饰器就派上用场了。

装饰器本身也是一个函数,作用就是为现有存在的函数,在不改变函数的基础上,增加一些功能进行装饰。

它是以闭包的形式去实现的。

在使用装饰器函数时,在被装饰的函数的前一行,使用@装饰器函数名形式来进行装饰。

Demo:

现在在一个项目中,有很多函数,由于我们的项目越来越大,功能也越来越多,导致程序越来越慢。

其中一个功能函数的功能是实现一百万次的累加。

计算函数的运行时间:

import time

def my_count():
    s=0
    for i in range(1000001):
        s+=i
        print('sum:,',s)

start=time.time()
my_count()
end=time.time()

print('执行时间为:,',(end-start)) #执行时间为:, 12.710999965667725

将上面时间计算函数封装

import time

def my_count():
    s=0
    for i in range(1000001):
        s+=i
    print('sum:,',s)

# start=time.time()
# my_count()
# end=time.time()
#
# print('执行时间为:,',(end-start))

def count_time(func):
    start=time.time()
    func
    end=time.time()
    print('执行时间为,',(end-start))

count_time(my_count())

经过修改后,定义一个函数来实现时间计算功能。

初看上去,比之前好很多。

只是在使用时,需要将对应的函数传入到时间计算函数中。

import time

def count_time(func):
    def wrapper():
        start=time.time()
        func()
        end=time.time()
        print((end-start))
    return wrapper


def my_count():
    s=0
    for i in range(1000001):
        s+=i
    print('sum:',s)
my_count=count_time(my_count)
my_count()
import time

def count_time(func):
    def wrapper():
        start=time.time()
        func()
        end=time.time()
        print((end-start))
    return wrapper

@count_time
def my_count():
    s=0
    for i in range(1000001):
        s+=i
    print('sum:',s)
# my_count=count_time(my_count)
my_count()

这样实现的好处,定义闭包函数后,只需要通过@装饰器函数名形式的装饰器语法,就可以将

@装饰器函数名加到要装饰的函数前即可。

这种不改变原有函数功能,对函数进行拓展的形式,就称为装饰器

在执行@装饰器函数名时,就是将原函数传递到闭包中。然后,原函数的引用指向闭包返回的装饰过的内部函数的引用。

装饰器的几种形式

1.无参无返回值

def setFunc(func):
    def wrapper():
        print('Start')
        func()
        print('end')
    return wrapper

@setFunc
def show():
    print('show')

show()
# Start
# show
# end

2.无参有返回值

def setFunc(func):
    def wrapper():
        print('Start')
        func()
        print('end')
    return wrapper

@setFunc
def show():
    return 'show'

print(show())
# Start
# end
# None
def setFunc(func):
    def wrapper():
        print('Start')
        return func()
        print('end') #return后面不再执行
    return wrapper

@setFunc
def show():
    return 'show'

print(show())
#Start
#show

3.有参无返回值

def setFunc(func):
    def wrapper(s):
        print('Start')
        func(s)
        print('end') 
    return wrapper

@setFunc
def show(s):
    print('Hello %s'%s)

show('City College')
#Start
#Hello City College
#end

4.有参有返回值

def setFunc(func):
    def wrapper(x,y):
        print('Start')
        return func(x,y)
        # print('end')
    return wrapper

@setFunc
def myAdd(x,y):
    return x+y

print(myAdd(3,3))
#Start
#6

万能装饰器

通过可变参数(*args/**kwargs)来接受不同的参数类型。

def setFunc(func):

    def wrapper(*args,**kwargs):
        print('Wrapper context.')
        return func(*args,**kwargs)

    return wrapper

@setFunc
def func(name,age,job='IT'):
    print(name,age,job)

func('Tom',18)

@setFunc
def demo(a,b,*c,**d):
    print((a,b))
    print(c)
    print(d)

demo('city','college',1999,1,1,school='zhejiang university')

Wrapper context.
Tom 18 IT
Wrapper context.
('city', 'college')
(1999, 1, 1)
{'school': 'zhejiang university'}

多个装饰器

#装饰器1
def setFunc1(func):
    def wrapper(*args,**kwargs):
        print(000)
        func(*args,**kwargs)
        print(111)

    return wrapper
#装饰器2
def setFunc2(func):

    def warpper2(*args,**kwargs):
        print(000)
        func(*args,**kwargs)
        print(111)

    return warpper2

@setFunc1                  #F
@setFunc2                  #g
def show(*args,**kwargs):  #f
    print('show run')

show() #F(g(f))

#从下往上去装饰(程序语句运行顺序来看)
#从内往外去装饰(从函数的调用来看)
0
0
show run
111
111

总结:

1.函数可以像普通变量一样,作为函数的参数或者返回值进行传递。

2.函数的内部可以定义另外一个函数。目的,隐藏函数功能的实现。

3.闭包实际上也是函数定义的一种形式。

4.闭包定义的规则,在外部函数内定义一个内部函数,内部函数使用外部函数的变量,并返回内部函数的引用。

5.Python中,装饰器就是用闭包来实现的。

6.装饰器的作用,不改变现有函数的基础上,为函数增加功能。

7.装饰器四种形式,根据参数的不同以及返回值的不同。

8.万能装饰器,通过可变参数(*args/**kwargs)来实现。

9.一个装饰器可以为多个函数提供装饰功能。

10.一个函数也可以被多个装饰器所装饰。

11.通过类实现装饰器,重写__init____call__函数。

12.类装饰器在装饰函数后,原来的引用不再是函数,而是装饰器的对象。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值