装饰器

""""
装饰器:本质是函数,为其他函数添加附加功能
    原则:不修改被修改的函数的源代码
        不修改被装饰的函数的调用方式
    使用方式:高阶函数 + 函数嵌套 + 闭包
高阶函数:函数的接收的参数是一个函数名
    函数的返回值是一个函数名
"""
# 例题:装饰器使用
# import time
# def timmer(func):     #高阶函数,参数是函数名,用于传需要装饰的函数
#     def wra(*args,**kwargs):     #函数嵌套,参数用*,**保证能传任意参数,且怎么传过来就传回去
#         start_time = time.time()
#         res = func(*args,**kwargs)#闭包:每一个嵌套相当于一个包,类似作用域,能调用外层变量
#         stop_time = time.time()
#         print("函数运行时间%s" %(stop_time - start_time))
#         return res      #给被装饰的函数一个返回值,注意返回值是与函数放在同一层级
#     return wra
# @timmer      #@相当于f = tiemer(f)
# def f(n):
#     s = 0
#     for i in range(n):
#         time.sleep(0.1)
#         s += i
#     return s        #必须在装饰器中给定这个函数的return,这个函数才会有返回值
# ret = f(10)
# print(ret)

"""
装饰器框架:
 def f(func):     #高阶函数,参数是函数名,用于传需要装饰的函数
     def s(*args,**kwargs):     #嵌套函数,使用*,**接收任意参数,接收的是被修饰的函数的参数,注意怎么接收就怎么传回去
         res = func(*args,**kwargs)   #闭包,调用外层的变量。这个地方的参数*,**是调用外层嵌套函数获得的参数
         return res   #给被装饰的函数一个返回值,注意这个return是放在装饰器中,与函数调用放在同一层级,放在被装饰函数中不会生成返回值
     return s     #返回嵌套函数

@f                #执行test = f(test),保证函数调用方式不变
def test():       #需要装饰的函数
"""
#设置一个网站认证
name_list = [
    {"name":"sjy","word":"123"},   #相当于一个数据库,可open文件打开数据
    {"name":"yue","word":"111"},   #用户名和密码是字符串,若在用户输入时做int转换,则就变成数字
    {"name":"yi","word":"222"}     #注意用户输入的类型,一般是以字符串形式
]
username_passwd = {"name":None,"login":False}    #定义一个全局变量来作为初始值
def atu_ty(atu_type="ldap"):   #想装饰器能够调用参数,则利用闭包,把装饰器嵌套到一个函数中
    def atu(func):
        def war(*args,**kwargs):
            if atu_type == "ldap":     #判断认证类型
                print("type is", atu_type)
                if username_passwd["name"] and username_passwd["login"]:     #先判断初始值是否为True
                    res = func(*args,**kwargs)         #当True时直接运行,跳过重新输入
                    return res
                username = input("name:")
                passwd = input("password:")      #这里输入的是字符串
                for i in name_list:
                    if username == i["name"] and passwd == i["word"]:    #做一个输入结果的认证判断
                        username_passwd["name"] = username       #将符合的结果更新到初始值,保留,再调用时不用再重新输入
                        username_passwd["login"] = True
                        res = func(*args,**kwargs)
                        return res
                else:         #此时else是在for循环用户列表结束后,都没有符合时再判否,若放在for循环内,只会判断其中一次是否符合
                    print("username or password of error")
                    war()
            elif atu_type == "filedb":     #其他的类型方式认证
                ...
                print("type is %s" %atu_type)
                res = func(*args, **kwargs)
                return res
            else:
                ...
                print("unknown type")
                res = func(*args, **kwargs)
                return res
        return war
    return atu    #装饰器嵌套在一个函数中,需返回函数,才能将装饰器调用起来
@atu_ty(atu_type="ldap")   #运行atu_ty函数,内部返回的值就是atu函数,就是在调用装饰器
def index():
    print("欢迎")
@atu_ty(atu_type="filedb")   #用不同类型进行认证
def shop():
    print("商品")
@atu_ty(atu_type="ss")
def pay():
    print("付款")

index()
shop()
pay()

 

posted @ 2019-04-10 01:05  saber゛  Views(219)  Comments(0)    收藏  举报