美文网首页
Python篇-装饰器

Python篇-装饰器

作者: TianTianBaby223 | 来源:发表于2018-11-01 21:38 被阅读18次

    一 : 装饰器demo及分析

    我们为函数添加一段附加功能,并且秉承着

    1. 不修改被修饰函数的源代码
    2. 不修改被修饰函数的调用方式

    这种非常炫酷的添加附加功能的方式叫做装饰器

    import time
    
    #时间装饰器
    def timmer(func):
        def wapper(*args,**kwargs):
            start_time = time.time()
            res = func(*args,**kwargs)
            stop_time = time.time()
            print('函数时间是 : %s' % (stop_time - start_time))
            return  res
        return wapper
    
    @timmer
    def cal(l):
        res = 0
        for i in l:
            time.sleep(0.1)
            res += i
        return res
    print(cal(range(20)))
    
    函数时间是 : 2.0555498600006104
    190
    

    二 : 闭包

    闭包说白了就是函数嵌套的另一种叫法,每层包都有自己的局部变量, 函数也要看成一种变量存放在自己那层的包中,每一层的嵌套 ,那一层就是一个包.

    def first(name):
        def second():
            name = "222"
            print(name)
            def third():
                name = "333"
                print("哈哈哈"+name)
            third()
        print(name)
        second()
    first('111')
    
    111
    222
    哈哈哈333
    

    三 : 装饰器推导

    装饰器 = 高阶函数 + 函数嵌套 + 闭包

    ① : 雏形

    虽然没有修改foo函数源代码,也没有修改foo函数调用方式,但是运行结果却多执行了一次

    def foo():
        time.sleep(3)
        print('来自foo')
    
    def timer(func):
        start_time = time.time()
        func()
        stop_time = time.time()
        print("运行时间为 : "+str(stop_time - start_time))
        return func
    
    foo = timer(foo)
    foo()
    
    来自foo
    运行时间为 : 3.002413034439087
    来自foo
    
    ② : 闭包

    利用闭包,(函数嵌套)将func函数传入内部执行,返回wrapper函数,赋值给test,再运行test()巧妙的解决了 步骤 ① 的问题

    def timmer(func):
        def wrapper():
            start_time = time.time()
            func()#运行test
            stop_time = time.time()
            print("运行时间" + str(stop_time - start_time))
        return wrapper
    
    def test():
        time.sleep(3)
        print("函数运行完毕")
    
     test = timmer(test) #返回是wrapper地址
     test() #执行的是wrapper()
    
    ③ : 语法糖

    将②步骤,修改成语法糖的形式 ,@timmer 相当于test = timmer(test)

    def timmer(func):
        def wrapper():
            start_time = time.time()
            func()#运行test
            stop_time = time.time()
            print("运行时间" + str(stop_time - start_time))
        return wrapper
    
    @timmer #test = timmer(test)
    def test():
        time.sleep(3)
        print("函数运行完毕")
    
    #语法糖 @timer就相当于 test = timmer(test)
     test()
    
    ④ : 增加返回值

    在③ 的基础上,添加了返回值.使得函数有返回值

    def timmer(func):
        def wrapper():
            start_time = time.time()
            res = func()#运行test
            stop_time = time.time()
            print("运行时间" + str(stop_time - start_time))
            return res
        return wrapper
    
    @timmer #test = timmer(test)
    def test():
        time.sleep(3)
        print("函数运行完毕")
        return "我是test"
    
    res = test()
    print(res)
    
    ⑤ : 增加参数

    在④的基础上增加参数,使得函数能够添加参数

    def timmer(func):
        def wrapper(*args,**kwargs):
            start_time = time.time()
            res = func(*args,**kwargs)#运行test
            stop_time = time.time()
            print("运行时间" + str(stop_time - start_time))
            return res
        return wrapper
    
    @timmer #test = timmer(test)
    def test(name,age):
        time.sleep(3)
        print("函数运行完毕名字 : %s 年龄 %s" %(name,age) )
        return "我是test"
    

    四 : 解压序列

    获取列表或元祖可以用解压队列对应的方式
    a获取1,b获取2 ,c获取3

    a,b,c = (1,2,3)
    print(a,b,c)
    

    取出庞大列表的第一项和倒数第一第二项
    其中假如想忽略中间的列表,*temp可以用*_替换

    a,*temp,b,d= [1,2,3,4,5,6,7]
    print(a)
    print(b)
    print(d)
    
    1
    6
    7
    [2, 3, 4, 5]
    

    python交换变量的另类方式

    f1 = 1
    f2 = 2
    f1,f2 = f2,f1
    

    五 : 装饰器添加参数

    ① 雏形 :

    功能 : 模拟一个用户登录的验证功能+session功能

    user_list = [
    {'name' : 'sisi','password':'123'},
    {'name' : 'keke','password':'123'},
    {'name' : 'nana','password':'123'},
    ]
    
    current_dic = {'username' : None,'login':False}
    def auth_func(func):
        def wrapper(*args,**kwargs):
    
            if current_dic['username'] and current_dic['login']:
                res = func(*args, **kwargs)
                return res
            username = input('用户名 :').strip()
            password = input('密码 :').strip()
            for dic in user_list:
                if username == dic['name'] and password == dic['password']:
                    current_dic['username'] = username
                    current_dic['login'] = True
                    res = func(*args, **kwargs)
                    return res
            else:
                print('用户名密码错误')
    
        return wrapper
    
    
    @auth_func
    def index():
        print("京东主页")
    
    @auth_func
    def home(name):
        print(name+"欢迎回家")
    
    @auth_func
    def shopping_car(name):
        print("%s的橘子" %name)
    
    
    index()
    
    home('雪芙')
    
    shopping_car("思思")
    
    ② 终极 :

    在①中,我们不能选择数据库,所以我们要为装饰器添加一个参数来,让其有选择数据库的功能,所以在①的基础上,外面又嵌套了一层.

    @auth(auth_type='filedb') 把@后面看成一个执行的函数返回值是 auth_func其本质还是 @auth_func, 只不过,运行调用一次auth(auth_type='filedb')我们可以在其中做相应的业务逻辑

    user_list = [
    {'name' : 'sisi','password':'123'},
    {'name' : 'keke','password':'123'},
    {'name' : 'nana','password':'123'},
    ]
    
    current_dic = {'username' : None,'login':False}
    
    
    def auth(auth_type = 'filedb'):
    
        def auth_func(func):
            def wrapper(*args,**kwargs):
                print(auth_type)
    
                if auth_type == "filedb":
                    if current_dic['username'] and current_dic['login']:
                        res = func(*args, **kwargs)
                        return res
                    username = input('用户名 :').strip()
                    password = input('密码 :').strip()
                    for dic in user_list:
                        if username == dic['name'] and password == dic['password']:
                            current_dic['username'] = username
                            current_dic['login'] = True
                            res = func(*args, **kwargs)
                            return res
                    else:
                        print('用户名密码错误')
                elif auth_type == 'ladp':
                    print('岑岑')
                else:
                    print("其他方式")
    
            return wrapper
        return auth_func
    
    @auth(auth_type='filedb')
    def index():
        print("京东主页")
    
    @auth(auth_type='ladp')
    def home(name):
        print(name+"欢迎回家")
    
    @auth(auth_type='xxx')
    def shopping_car(name):
        print("%s的橘子" %name)
    
     index()
    
     home('雪芙')
    
    shopping_car("思思")
    
    

    相关文章

      网友评论

          本文标题:Python篇-装饰器

          本文链接:https://www.haomeiwen.com/subject/dakbtqtx.html