zoukankan      html  css  js  c++  java
  • 〖Python〗-- 装饰器

    【装饰器】

    一、什么是装饰器

    器即函数

    装饰即修饰,意指为其他函数添加新功能

    装饰器定义:本质就是函数,功能是为其他函数添加新功能 #装饰器本身就是函数,被装饰的也是函数。

    为什么要用装饰器:
    及开放封闭原则。
    代码上线后,就是为了尽量避免修改,不修改原函数的源代码和调用方式,并添加新的功能。 # 函数及定义和使用。

    装饰器语法:

    在被装饰上的正上方写一个@,它会把@这一行下面这一行的函数传递到函数里,再重新赋值给index。

    func就是index函数,print(func)返回得是index内存地址。

    无参装饰器:

    (1):

    1
    2
    3
    输出:
    welcome to oldboy
    run time is 3.000171661376953

    执行过程:

    # 函数应该先定义后使用。
    import time
    def timmer(func): # 定义函数就相当于定义变量名,就相当于把函数的代码绑定到一个名字上面了。 #1,定义变量名 #3 func值就是index
        def wrapper(): #4 开始执行timmer里面的代码,只要碰到def就跟定义变量名一样,它里边定义的代码全不用管,只要不执行就不用管它。#7
            start_time=time.time() #8
    #        print(func)
            func() #9 func就是最原始的index
            stop_time=time.time() #14
            print('run time is %s' %(stop_time-start_time)) #15
        return wrapper #5 return wrapper 就是return wrapper的内存地址
     
    # index=timmer(index) 
    @timmer #2 timmer要运行timmer(index),所以要跳回去 #10
    def index(): #11
        time.sleep(3) #12
        print('welcome to oldboy') #13
    index() #6 index就是wrapper函数,wrapper是一个闭包函数,里边包含了一个状态,就是func。
    示例

    (2): # 第一次是home,第二次是home("name")

    1
    2
    3
    4
    5
    6
    7
    输出:
    welcome to dragon home page
    run time is 2.0001144409179688
    egon 123
    run time is 0.0
    ------------
    run time is 0.0

    注意:传参数,需要加上*args,**kwargs

    (3):

    1
    2
    3
    4
    输出:
    my_max function
    run time is 0.0
    -------- 2

    注意:如果原函数需要有返回值,则装饰器也需要设置return res。完整正确的无参装饰器写法就是以上写法。 

    有参装饰器:

    (1): #第一步是函数()的效果,第二步是@auth的效果

    1
    输出:还他妈的不会玩
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    #有参函数执行流程
    def auth2(auth_type): #1 #3
        def auth(func): #4 #6
            def wrapper(*args,**kwargs): #7 #10
                if auth_type == 'file'#11
                    name=input('username: ')
                    password=input('password: ')
                    if name == 'zhejiangF4' and password == 'sb945':
                        print('auth successfull')
                        res=func(*args,**kwargs)
                        return res
                    else:
                        print('auth error')
                elif auth_type == 'sql'#12
                    print('还他妈不会玩'#13
            return wrapper #8
        return auth #5
     
    @auth2(auth_type='sql'#2
    def index():
        print('welcome to inex page')
     
    # @auth
    # def home():
    #     print('welcome to home page')
    index() #9

    多个装饰器:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    #多个无参装饰器:
    # @aaa
    # def func():
    #     pass
    #
    # func=aaa(func)
     
    # @ccc
    # @bbb
    # @aaa
    # def func():
    #     pass
    #
    # func=ccc(bbb(aaa(func)))
     
    #多个有参装饰器
    # @ccc('c')
    # @bbb('b')
    # @aaa('a')
    # def func():
    #     pass
    #
    # func=ccc('c')(bbb('b')(aaa('a')(func)))

    多个装饰器应用:

    import time
    current_login={'name':None,'login':False}
     
    def timmer(func):
        def wrapper(*args,**kwargs):
            start_time=time.time()
            res=func(*args,**kwargs)  #my_max(1,2)
            stop_time=time.time()
            print('run time is %s' %(stop_time-start_time))
            return res
        return wrapper
     
    def auth2(auth_type='file'):
        def auth(func):
            # print(auth_type)
            def wrapper(*args,**kwargs):
                if current_login['name'] and current_login['login']:
                    res=func(*args,**kwargs)
                    return res
                if auth_type == 'file':
                    name=input('username: ')
                    password=input('password: ')
                    if name == 'luchuan' and password == '123':
                        print('auth successfull')
                        res=func(*args,**kwargs)
                        current_login['name']=name
                        current_login['login']=True
                        return res
                    else:
                        print('auth error')
                elif auth_type == 'sql':
                    print('还他妈不会玩')
            return wrapper
        return auth
     
    @timmer
    @auth2(auth_type='file') #@auth  #index=auth(index)
    def index():
        print('welcome to inex page')
     
    @auth2()
    def home():
        print('welcome to home page')
     
     
     
    #调用阶段
    index()
    home()
    View Code

    装饰器帮助信息补充:

    import time
    from functools import wraps
    def timmer(func):
        @wraps(func)
        def wrapper(*args,**kwargs):
            'sssssssssssss' # 不加wraps,就会返回'sssssss'帮助信息
            start_time=time.time()
            func(*args,**kwargs) #home(name)
            stop_time=time.time()
            print('run time is %s' %(stop_time-start_time))
        return wrapper
     
     
    @timmer
    def func(x):
        'func test'
        print(x)
     
    func(1)
    print(func.__doc__)  # 查看帮助信息的两种方式
    # print(help(func))
     
    #不加wraps,输出sssssssss
    #加上wraps,则输出:from test
    View Code

    二、装饰器需要遵循的原则

    1.不修改被装饰函数的源代码(开放封闭原则)

    2.为被装饰函数添加新功能后,不修改被修饰函数的调用方式

    三、实现装饰器知识储备

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

    装饰器:一个外部函数、一个内部函数、一个return 、如果是有参装饰器,外部再包一层函数。

    四、高阶函数

    高阶函数定义:
    1.函数接收的参数是一个函数名

    2.函数的返回值是一个函数名

    3.满足上述条件任意一个,都可称之为高阶函数

    def foo():
        print('我的函数名作为参数传给高阶函数')
    def gao_jie1(func):
        print('我就是高阶函数1,我接收的参数名是%s' %func)
        func()
    
    def gao_jie2(func):
        print('我就是高阶函数2,我的返回值是%s' %func)
        return func
    
    gao_jie1(foo)
    gao_jie2(foo)
    高阶函数示范
    #高阶函数应用1:把函数当做参数传给高阶函数
    import time
    def foo():
        print('from the foo')
    
    def timmer(func):
        start_time=time.time()
        func()
        stop_time=time.time()
        print('函数%s 运行时间是%s' %(func,stop_time-start_time))
    timmer(foo)
    #总结:我们确实为函数foo增加了foo运行时间的功能,但是foo原来的执行方式是foo(),现在我们需要调用高阶函数timmer(foo),改变了函数的调用方式
    把函数当做参数传给高阶函数
    #高阶函数应用2:把函数名当做参数传给高阶函数,高阶函数直接返回函数名
    import time
    def foo():
        print('from the foo')
    
    def timmer(func):
        start_time=time.time()
        return func
        stop_time=time.time()
        print('函数%s 运行时间是%s' %(func,stop_time-start_time))
    foo=timmer(foo)
    foo()
    #总结:我们确实没有改变foo的调用方式,但是我们也没有为foo增加任何新功能
    函数返回值是函数名

    高阶函数总结

    1.函数接收的参数是一个函数名
      作用:在不修改函数源代码的前提下,为函数添加新功能,
      不足:会改变函数的调用方式
    2.函数的返回值是一个函数名
      作用:不修改函数的调用方式
      不足:不能添加新功能

    五、函数嵌套

     
    def father(name):
        print('from father %s' %name)
        def son():
            print('from son')
            def grandson():
                print('from grandson')
            grandson()
        son()
    
    father('林海峰')
     

    六、闭包

     
    '''
    闭包:在一个作用域里放入定义变量,相当于打了一个包
    '''
    def father(name):
        def son():
            # name='alex'
            print('我爸爸是 [%s]' %name)
            def grandson():
                # name='wupeiqi'
                print('我爷爷是 [%s]' %name)
            grandson()
        son()
    
    father('林海峰')
     

    七、无参装饰器

    无参装饰器=高级函数+函数嵌套

    基本框架

    1 #这就是一个实现一个装饰器最基本的架子
    2 def timer(func):
    3     def wrapper():
    4         func()
    5     return wrapper

    加上参数

    1 def timer(func):
    2     def wrapper(*args,**kwargs):
    3         func(*args,**kwargs)
    4     return wrapper

    加上功能

    1 import time
    2 def timer(func):
    3     def wrapper(*args,**kwargs):
    4         start_time=time.time()
    5         func(*args,**kwargs)
    6         stop_time=time.time()
    7         print('函数[%s],运行时间是[%s]' %(func,stop_time-start_time))
    8     return wrapper

     加上返回值

    1 import time
    2 def timer(func):
    3     def wrapper(*args,**kwargs):
    4         start_time=time.time()
    5         res=func(*args,**kwargs)
    6         stop_time=time.time()
    7         print('函数[%s],运行时间是[%s]' %(func,stop_time-start_time))
    8         return res
    9     return wrapper

    使用装饰器

    1 def cal(array):
    2     res=0
    3     for i in array:
    4         res+=i
    5     return res
    6 
    7 cal=timer(cal)
    8 cal(range(10))

    语法糖@

    1 @timer  #@timer就等同于cal=timer(cal)
    2 def cal(array):
    3     res=0
    4     for i in array:
    5         res+=i
    6     return res
    7 
    8 cal(range(10))

    八、装饰器应用示例

    user_list=[
        {'name':'alex','passwd':'123'},
        {'name':'linhaifeng','passwd':'123'},
        {'name':'wupeiqi','passwd':'123'},
        {'name':'yuanhao','passwd':'123'},
        {'name':'病毒尖er','passwd':'123'},
    ]
    current_user={'username':None,'login':False}
    
    def auth_func(func):     # 用户登陆验证
        def bar(*args,**kwargs):
            if current_user["username"] and current_user["login"]:
                res = func(*args,**kwargs)
                return res
            for i in range(3):
                username = input("请输入用户名:").strip()
                passwd = input("请输入密码:").strip()
                for item in user_list:
                    if username == item["name"] and passwd == item["passwd"]:
                        current_user["username"] = username
                        current_user["login"] = True
                        res=func(*args,**kwargs)
                        return res
            else:
                print("您输入的用户名或者密码有误")
        return bar
    @auth_func # 相当于index=auth_func(index)
    def index():
        print("欢迎来到京东商城" )
    @auth_func # 相当于home=auth_func(home)
    def home(name):
        print("%s欢迎回家" %name)
    @auth_func # 相当于shop_car=auth_func()
    def shop_car(name):
        print("%s的购物车是空的,赶紧购物咯" %name)
    
    index()
    home(current_user["username"])
    shop_car(current_user["username"])
    无参装饰器
    user_list=[
        {'name':'alex','passwd':'123'},
        {'name':'linhaifeng','passwd':'123'},
        {'name':'wupeiqi','passwd':'123'},
        {'name':'yuanhao','passwd':'123'},
        {'name':'病毒尖er','passwd':'123'},
    ]
    current_user={'username':None,'login':False}
    def auth(auth_type="file"):
        def auth_func(func):     # 用户登陆验证
            def bar(*args,**kwargs):
                if auth_type == "file":
                    if current_user["username"] and current_user["login"]:
                        res = func(*args,**kwargs)
                        return res
                    for i in range(3): # 给用户三次重复输入的机会 防止进入其它功能进入下一层
                        username = input("请输入用户名:").strip()
                        passwd = input("请输入密码:").strip()
                        for item in user_list:
                            if username == item["name"] and passwd == item["passwd"]:
                                current_user["username"] = username
                                current_user["login"] = True
                                res=func(*args,**kwargs)
                                return res
                    else:
                        print("您输入的用户名或者密码有误")
                elif auth_type == "ldap":
                    print("快点告诉你,你用我画的蜡笔")
                    res = func(*args,**kwargs)
                    return res
            return bar
        return auth_func
    @auth(auth_type="file")
    def index():
        print("欢迎来到京东商城" )
    @auth(auth_type="ldap")  # 传参数 类型对应
    def home(name):
        print("%s欢迎回家" %name)
    @auth(auth_type="file")
    def shop_car(name):
        print("%s的购物车是空的,赶紧购物咯" %name)
    
    index()
    home(current_user["username"])
    shop_car(current_user["username"])
    有参装饰器
  • 相关阅读:
    数据库事务隔离级别-- 脏读、幻读、不可重复读
    【洛谷7518】[省选联考 2021 A/B 卷] 宝石(树上倍增+并查集)
    【CF666D】Chain Reaction(暴搜+细节讨论)
    【洛谷5064】[Ynoi2014] 等这场战争结束之后(操作树+值域分块)
    【洛谷7437】既见君子(状压+矩阵树定理)
    【洛谷5046】[Ynoi2019 模拟赛] Yuno loves sqrt technology I(分块)
    【LOJ2462】「2018 集训队互测 Day 1」完美的集合(树上连通块问题+扩展卢卡斯)
    【洛谷4339】[ZJOI2018] 迷宫(神仙题)
    【CF639E】Bear and Paradox(贪心+二分)
    【洛谷5444】[APIO2019] 奇怪装置(数论)
  • 原文地址:https://www.cnblogs.com/SHENGXIN/p/7426402.html
Copyright © 2011-2022 走看看