装饰器及其应用

1.写在前面

1.1为什么要有装饰器(decorator)

  一般在写好的系统中,函数是不允许随便更改的,以免发生不可预见的连环崩溃。但是,随着系统的更新一些必要的功能必须要加到相应的函数中。

这样的情况下,就需要用到装饰器。装饰器本身也是一个函数,写在目标函数的前面。原理形象地将就是将目标函数装饰一下但是函数本身没变。

1.2什么是闭包

1 def outer():
2     x = 10
3     def inner():  
4         print(x)  
5     return inner   
6 
7 f = outer()
View Code

上述的代码中inner就是一个闭包。原因有两个:

(1)它是一个内部的函数

(2)它引用了encolsing的变量

那么在运行f()的时候会打印x

2.装饰器

有两个函数:

1 import time
2 def func1():         
3     print("func1")
4     time.sleep(1)
5 def func2():
6     print("func2")
7     time.sleep(2)

function函数是密封好的两个目标函数,现在想在这两个函数上加上计时功能,且不改变函数。传统方法:

1 def time_count(func):           
2     start_time = time.time()    
3     func()
4     end_time = time.time()
5     return print(end_time-start_time)
6 time_count(func1)

有了这个count函数就可以直接在function函数上加上计时功能,但是存在的问题是:这个函数改变了调用函数的方式,变为了调用time_count。这样的缺陷在实际生产中部允许的。于是有:

import time
def time_count(func):
    def inner():
        ########################################## 装饰器函数
        start_time = time.time()     # 这四行就是添加功能后的功能函数
        func()                       # 此时这四行就是运行后的func1
        end_time = time.time()
        print(end_time-start_time)
        ##########################################
    return inner       # 很关键

@time_count # func1 = time_count(func1)  经过这一步 func1中储存的是inner的地址 并且只有这句会先运行,其他都是函数进内存
def func1():                         # 功能函数1
    print("func1")
    time.sleep(1)

@time_count
def func2():
    print("func2")
    time.sleep(2)
func1()

代码中注释内容已经很好的展现了装饰器的实现过程。通过@这个方法将function在运行之前已经变成了装饰器函数中的inner函数。

这里还需要了解解释器在运行时的顺序:三个函数进内存 2 执行第一个@ func1变为inner 执行第二个@。。。 3 执行func()

3.带参数的装饰器

带参数装饰器的作用是:根据目标函数的不同需求来在装饰器中执行不同的功能。看下面的例子:页面登陆。

def para_decorator(f_para_pd):
    def decorator(f_para_dec):
        def func():
            if log_status == True:
                global source
                sf = source[f_para_pd]["name"]
                print("welcome user {kk}".format(kk=sf))
                f_para_dec()
            if log_status == False:
                if f_para_pd == "jingdong":
                    info_match(f_para_pd)
                    f_para_dec()
                elif f_para_pd == "weixin":
                    info_match(f_para_pd)
                    f_para_dec()
                elif f_para_pd == "qq":
                    info_match(f_para_pd)
                    f_para_dec()
        return func
    return decorator

这是一个带参数的装饰器的核心内容。该函数有嵌套了三个函数:parameter_decorator 》decorator》func 其实就是在装饰器函数的基础上加上了一层函数。这层函数并没有实际的多少代码。它 的最重要的一个作用就是将一个parameter带入了装饰器中。这样在执行func中的功能中可根据它来调整。

原文地址:https://www.cnblogs.com/khal-Cgg/p/5872338.html