函数的装饰器

装饰器的本质:一个闭包函数

  装饰器的功能:在不修改原函数及其调用方式的情况下对原函数功能进行扩展

import time
def timer(func):
    def inner():
        start = time.time()
        func()
        print(time.time() - start)
    return inner

@timer   #==> func1 = timer(func1)
def func1():
    print('in func1')


func1()

完整的装饰,万能的装饰

def timmer(qqxing):   #timmer是装饰器的名字,传入的参数就是被装饰的函数
    def inner(*args,**kwargs):      #在装饰器中需要定义一个内部函数
        print('调用func之前')
        ret = qqxing(*args,**kwargs)      #被装饰的函数,并且要执行
        print('调用func之后')
        return ret
    return inner      #将内部函数的名字返回

@timmer   #语法糖  func = timmer(func)
def func(name):
    print('%s的公司好老板好同事好'%(name))
    return 1111111111

ret = func('俊杰')
print('result : %s'%ret)

输出:
调用func之前
俊杰的公司好老板好同事好
调用func之后
result : 1111111111

装饰器的固定结构:

#装饰器的固定结构
def wrapper(func):
    def inner(*args,**kwargs):
        """被装饰函数执行之前要添加的代码"""
        ret = func(*args,**kwargs)
        """被装饰函数执行之后要添加的代码"""
        return ret
    return inner

多个装饰器装饰同一个函数

有些时候,我们也会用到多个装饰器装饰同一个函数的情况。

def wrapper1(func):
    def inner():
        print('wrapper1 ,before func')
        func()
        print('wrapper1 ,after func')
    return inner

def wrapper2(func):
    def inner():
        print('wrapper2 ,before func')
        func()
        print('wrapper2 ,after func')
    return inner

@wrapper2
@wrapper1
def f():
    print('in f')

f()

开放封闭原则

  1.对扩展是开放的

    为什么要对扩展开放呢?

    我们说,任何一个程序,不可能在设计之初就已经想好了所有的功能并且未来不做任何更新和修改。所以我们必须允许代码扩展、添加新功能。

  2.对修改是封闭的

    为什么要对修改封闭呢?

    就像我们刚刚提到的,因为我们写的一个函数,很有可能已经交付给其他人使用了,如果这个时候我们对其进行了修改,很有可能影响其他已经在使用该函数的用户。

装饰器完美的遵循了这个开放封闭原则。

练习:

#用装饰器实现,访问art或者dar函数,登陆一次之后,无需再次登录
# art()
# dar()

flag = False

def login(func):
    def inner(*args,**kwargs):
        global flag
        if flag == False:
            username = input('用户名:')
            password = input('密码:')
            if username == 'alex' and password == 'somebody':
                print('登录成功')
                flag = True
        if flag == True:
            ret = func(*args,**kwargs)
            return ret
    return inner

@login
def art():
    print('欢迎来到文章页')

@login
def dar():
    print('欢迎来到日记页')

dar()
art()

输出:
用户名:alex
密码:somebody
登录成功
欢迎来到日记页
欢迎来到文章页

实现日志功能:

def log(func):
    def inner(*args,**kwargs):
        print('你要调用%s函数了'%func.__name__)
        ret = func(*args,**kwargs)
        return ret
    return inner

@log  #f1 = log(f1)
def f1():
    print('f1')
@log
def f2():
    print('f2')

#日志
f1()
f2()

输出:
你要调用f1函数了
f1
你要调用f2函数了
f2
import time
def timer(func):
    def inner(*args,**kwargs):
        start = time.time()
        re = func(*args,**kwargs)
        print(time.time() - start)
        return re
    return inner

@timer   #==> func2 = timer(func2)
def func2(a):
    print('in func2 and get a:%s'%(a))
    return 'fun2 over'


print(func2(2))  # 'fun2 over'

输出:
in func2 and get a:2
0.0009996891021728516
fun2 over

 装饰器进阶:

进阶一:

def outer(flag):
    def wrapper(func):
        def inner(*args,**kwargs):
            if flag:
                print('执行%s之前我加了一个功能'%func.__name__)
            ret = func(*args,**kwargs)  #qqxing
            return ret
        return inner
    return wrapper
@outer(True)      #qqxing = wrapper(qqxing)
def qqxing():
    print('qqxing')

@outer(False)    #wahaha  = wrapper(wahaha)
def wahaha():
    print('wahaha')

qqxing()
wahaha()
#2000
#1000
#1000

# def outer(flag,flag2):
#     def wrapper(func):
#         def inner(*args,**kwargs):
#             ret = func(*args,**kwargs)
#             return ret
#         return inner
#     return wrapper
#
# @outer(True,False)   #带参数的装饰器 ==》@wrapper ==》func = wrapper(func) ==>  func == inner
# def func():pass


进阶二:

def wrapper2(func):     #inner1
    def inner2(*args,**kwargs):
        print('in wrapper 2,before')
        ret = func(*args,**kwargs)   #inner1
        print('in wrapper 2,after')
        return ret
    return inner2
def wrapper1(func):    #qqxing
    def inner1(*args,**kwargs):
        print('in wrapper 1,before')
        ret = func(*args,**kwargs)   #qqxing
        print('in wrapper 1,after')
        return ret
    return inner1


@wrapper1       #qqxing = inner1
@wrapper2       #qqxing = wrapper2(inner1)  = inner2
def qqxing():
    print('qqxing')

qqxing()    #inner2


#login  一个实现login的装饰器
#timmer 一个计算函数时间的装饰器

#先登录,再计算时间
原文地址:https://www.cnblogs.com/biluo/p/7789308.html