装饰器

装饰器

  一、装饰器定义:本质就是函数,功能是为其它函数添加附加功能

原则:
1、不修改被修饰函数的源代码
2、不修改被修饰函数的调用方式
装饰器的知识储备
装饰器=高阶函数+函数嵌套+闭包


二、高阶函数
高阶函数定义:
1、函数接受的参数是一个函数名
2、函数的返回值是一个函数名
3、满足上述条件任意一个,都称为高阶函数
def foo():
    print('您好啊赵师傅')  #4、打印
    return foo  #5、return 

def test(func):  #2、接受foo参数,代入函数体
    func()    #3、执行foo函数

test(foo) #1、执行test函数,传参foo

执行结果:
您好啊赵师傅

三、在遵循装饰器原则的基础上,修改上述代码,增加计时功能;

ps1:

import time
#满足条件1:作用是,可以在不修改源代码的情况下,为被修改函数foo添加新功能
#问题是,修改了foo的调用方式
def foo():
  time.sleep(2)
print('您好啊赵师傅') def test(func): start_time = time.time()  #计算开始时间 func()  #执行foo函数 stop_time = time.time()  #计算结束时间 print('执行函数所用时间:【%s】'%(stop_time-start_time))  #结束时间减去开始时间为运行时间 test(foo)

执行结果:
您好啊赵师傅
执行函数所用时间:【2.0001139640808105】

ps2:

#满足条件:
#1、不修改foo源代码
#2、不修改foo调用方式
#但是多调用一次,不满足业务需求
def foo():  
    print('您好啊赵师傅')  #3、调用函数打印信息

def test(func):
    start_time = time.time()
    func()    #2、执行传入的foo函数
    stop_time = time.time()    
    print('执行函数所用时间:【%s】'%(stop_time-start_time))   #4、打印时间
    return func #返回foo函数值
foo=test(foo)  #1、执行函数test(foo),并把foo传入函数体/ #6、foo变量接受return的foo()函数的内存地址
foo()  #7、得到内存地址,再次执行了一遍foo函数

执行结果:
您好啊赵师傅
执行函数所用时间:【0.0】
您好啊赵师傅

四、函数嵌套、闭包概念

函数嵌套定义:函数内部再定义函数
闭包概念:封装内层的变量值(函数也是变量)
ps1:
def father(name):
    def son():
        print('我的父亲是%s'%name) #3、打印
        def grandson():
            print('我的爷爷是%s'%name) #5、打印
        grandson()  #4、调用grandson()
    son() #2、调用son()

father('zk') #1、调用father函数,传参zk给函数体

执行结果:
我的父亲是zk
我的爷爷是zk

五、装饰器基本架子

ps1:基础架子

def timer(func):  
    def wrapper():
        func()  
    return wrapper

ps2:加上参数

def timer(func):
    def wrapper(*args,**kwargs):  #接受实际函数所传的参数,给wrapper函数内部调用
        func(*args,**kwargs)  #将参数
    return wrapper

ps3:加上功能

import time
def timer(func):
    def wrapper(*args,**kwargs):
        start_time=time.time()  #可加上具体功能
        func(*args,**kwargs)   #func为外层变量,在内层可以获取到
        stop_time=time.time()
        print('函数[%s],运行时间是[%s]' %(func,stop_time-start_time))
    return wrapper

ps4:加上返回值

import time
def timer(func):
    def wrapper(*args,**kwargs):
        start_time=time.time()
        res=func(*args,**kwargs)  #返回实际执行函数的返回值,用个变量接收到
        stop_time=time.time()
        print('函数[%s],运行时间是[%s]' %(func,stop_time-start_time))
        return res  #在返回得到的变量的值,这时wrapper的返回值,就是实际执行函数的返回值了
    return wrapper

装饰器调用解析:

ps1:

def timer(func):  #func————>test
    def wrapper():
        func()  #就是在运行test函数
    return wrapper


#———————————————以上部分是基本架子—————————————————————

def test():
    print('test执行完毕')

res=timer(test) #返回的是wrapper的内存地址    用res接收wrapper的内存地址
res()  #执行的是wrapper函数

语法糖@

@timer  #@timer就等同于res=timer(test)   后两句
def timer(func):  #func————>test
    def wrapper():
        func()  #就是在运行test函数
    return wrapper
def test():
    print('test执行完毕')

#res=timer(test) #返回的是wrapper的内存地址    用res接收wrapper的内存地址
#res()  #执行的是wrapper函数

无参数装饰器实例

user_list=[
    {'name':'alex','passwd':'123'},
    {'name':'linhaifeng','passwd':'123'},
    {'name':'wupeiqi','passwd':'123'},
    {'name':'yuanhao','passwd':'123'},
]

current_user={'username':None,'login':False}

def auth_deco(func):
    def wrapper(*args,**kwargs):
        if current_user['username'] and current_user['login']:
            res=func(*args,**kwargs)
            return res
        username=input('用户名: ').strip()
        passwd=input('密码: ').strip()

        for index,user_dic in enumerate(user_list):
            if username == user_dic['name'] and passwd == user_dic['passwd']:
                current_user['username']=username

                current_user['login']=True
                res=func(*args,**kwargs)
                return res
                break
        else:
            print('用户名或者密码错误,重新登录')

    return wrapper

@auth_deco
def index():
    print('欢迎来到主页面')

@auth_deco
def home():
    print('这里是你家')

def shopping_car():
    print('查看购物车啊亲')

def order():
    print('查看订单啊亲')

print(user_list)
# index()
print(user_list)
home()

无参装饰器

带参数装饰器实例

user_list=[
    {'name':'alex','passwd':'123'},
    {'name':'linhaifeng','passwd':'123'},
    {'name':'wupeiqi','passwd':'123'},
    {'name':'yuanhao','passwd':'123'},
]

current_user={'username':None,'login':False}
def auth(auth_type='file'):
    def auth_deco(func):
        def wrapper(*args,**kwargs):
            if auth_type == 'file':
                if current_user['username'] and current_user['login']:
                    res=func(*args,**kwargs)
                    return res
                username=input('用户名: ').strip()
                passwd=input('密码: ').strip()

                for index,user_dic in enumerate(user_list):
                    if username == user_dic['name'] and passwd == user_dic['passwd']:
                        current_user['username']=username
                        current_user['login']=True
                        res=func(*args,**kwargs)
                        return res
                        break
                else:
                    print('用户名或者密码错误,重新登录')
            elif auth_type == 'ldap':
                print('ldap___模式')
                res=func(*args,**kwargs)
                return res
        return wrapper
    return auth_deco


#auth(auth_type='file')就是在运行一个函数,然后返回auth_deco,所以@auth(auth_type='file')
#就相当于@auth_deco,只不过现在,我们的auth_deco作为一个闭包的应用,外层的包auth给它留了一个auth_type='file'参数
@auth(auth_type='ldap')
def index():
    print('欢迎来到主页面')

@auth(auth_type='ldap')
def home():
    print('这里是你家')

def shopping_car():
    print('查看购物车啊亲')

def order():
    print('查看订单啊亲')

# print(user_list)
index()
# print(user_list)
home()

带参装饰器

 自己写的练习题:

user_list=[
    {'user':'','passwd':'111111'},
    {'user':'','passwd':'111111'}
]

operating_dic={'user_name':None,'login_zt':False}
def jd_date(my_db='mysql'):
    def jd_yz(func):
        def wrapper(*arg,**kwargs):
            if my_db=='mysql':
                if operating_dic['user_name'] and operating_dic['login_zt']:
                    print(operating_dic)
                    res=func(*arg,**kwargs)
                    return res
                else:
                    user=str(input('用户名:'))
                    passwd=str(input('密码:'))
                    for i in user_list:
                        if user==i['user'] and passwd==i['passwd']:
                            operating_dic['user_name']=user
                            operating_dic['login_zt']=True
                            res=func(*arg,**kwargs)
                            return res
                    else:
                        print('用户名密码错误!!!')
            elif my_db =='sql_server':
                print('使用sql_server数据库验证')
            else:
                print('谁知道你用的是鸟验证')
        return wrapper
    return jd_yz
@jd_date(my_db='mysql')
def index(name):
    print('欢迎%s来到京东'%(name))

@jd_date(my_db='sql_server')
def home(name):
    print('欢迎%s回家'%(name))

@jd_date(my_db='abc')
def order(name):
    print('%s的订单'%(name))

index('zk')
home('zk')
order('zk')
原文地址:https://www.cnblogs.com/shangpolu/p/6143162.html