• python基础之装饰器


    一 什么是装饰器

    器即函数

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

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

    为什么要用装饰器:

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

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

    代码上线后,就是为了尽量避免修改,不修改原函数的源代码和调用方式。 # 函数及定义和使用。

    装饰器语法:

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

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

    二 装饰器需要遵循的原则

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

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

    (1)无参装饰器:

    不用传参数来使用装饰器。

      以下的操作是为函数foo来增加新的计时功能:不改变原函数的代码和调用方式

    import time #调用time模块
     
    def timmer(func): #装饰器timmer,将函数foo的函数名为参数传给timmer
        def wrapper():#嵌套函数
            start_time = time.time()#开始时间
            func() #func=函数foo的内存地址加括号函数是可以直接被调用的
            stop_time = time.time() #结束时间
            print("函数运行的时间是%s"%(stop_time-start_time))
        return wrapper #返回wrapperde 值
     
    @timmer #装饰器的语法@+装饰器名,foo = timmer(foo)
    def foo(): #定义的一个无参函数
        time.sleep(2) #使程序睡眠2s
        print("welcome to beijing")
     
    foo() #调用foo函数
    ---------------------以下是输出结果----------------------
        welcome to beijing
        函数运行的时间是2.0

    (2)

    要传参数来使用装饰器。

      以下的操作是为函数my_max来增加新的计时功能:不改变原函数的代码和调用方式

    import time #调用time模块
     
    def timmer(func): #嵌套函数
        def wrapper(*args,**kwargs):#接收参数
            start_time = time.time() #开始计时
            func(*args,**kwargs) #通过内存地址加括号里接收的参数来调用函数
            stop_time = time.time() #结束计时
            print("函数的运行时间是%s"%(stop_time-start_time))
        return wrapper #返回wrapper的值
     
    @timmer #my_max=timmer(my_max)#为my_max这个函数增加计时功能
    def my_max(x,y): #比较两个数的大小
        time.sleep(3) #睡眠3s,方便实验效果
        res = x if x > y else y #判断x与y的大小
        print("from the my_max,the max is %s"%res)
     
    my_max(1,2) #调用函数并按位置传参
    ---------------------以下是输出结果-----------------------
        from the my_max,the max is 2
        函数的运行时间是3.0

    三 实现装饰器知识储备

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

    四 高阶函数

    高阶函数定义:
    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无参装饰器3

    有参装饰器

    #为什么要用装饰器及开放封闭原则
    
    #什么是装饰器
    # import time
    # def timmer(func):
    #     def wrapper(*args,**kwargs):
    #         start=time.time()
    #         res=func(*args,**kwargs)
    #         stop=time.time()
    #         print('run time is %s ' %(stop-start))
    #     return wrapper
    #
    #
    # @timmer
    # def index():
    #     time.sleep(3)
    #     print('welcome to oldboy')
    #
    # index()
    
    
    
    
    
    #装饰器
    # import time
    #
    # @名字     #home=名字(home)
    # def home():
    #     time.sleep(3)
    #     print('welcome to oldboy')
    #
    # index()
    
    
    # def get(url):
    #     def index():
    #         return urlopen(url).read()
    #     return index
    
    
    import time
    def timmer(func): #func=home
        def wrapper():
            # print(func)
            start_time=time.time()
            func()
            stop_time=time.time()
            print('run time is %s' %(stop_time-start_time))
        return wrapper
    
    
    # index=timmer(index)
    @timmer
    def index():
        time.sleep(3)
        print('welcome to oldboy')
    
    @timmer
    def home(name):
        time.sleep(2)
        print('welcome to %s home page' %name)
    
    # def my_max(x,y):
    #     print('from my_max func')
    #     return x+y
    
    # index()  #--=--->wrapper()
    home('dragon')
    无参装饰器1
    import time
    def timmer(func):
        def wrapper(*args,**kwargs):
            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 #home=timmer(home)
    def home(name):
        time.sleep(2)
        print('welcome to %s home page' %name)
    
    
    
    
    @timmer  #auth=timmer(auth)
    def auth(name,password):
        print(name,password)
    
    @timmer
    def tell():
        print('-=----------')
    home('dragon')  #wrapper('dragon')
    auth('egon','123') #wrapper('egon','123')
    tell()
    无参装饰器2
    import time
    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
    
    
    @timmer
    def my_max(x,y):
        print('my_max function')
        res=x if x > y else y
        return res
    
    res=my_max(1,2) #res=wrapper(1,2)
    print('=====>',res)
    无参装饰器3
    def auth2(auth_type):
        def auth(func):
            # print(auth_type)
            def wrapper(*args,**kwargs):
                if auth_type == 'file':
                    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':
                    print('还他妈不会玩')
            return wrapper
        return auth
    
    @auth2(auth_type='sql') #@auth  #index=auth(index)
    def index():
        print('welcome to inex page')
    
    # @auth
    # def home():
    #     print('welcome to home page')
    index()
    有参装饰器
    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
    装饰器执行流程
    # @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 == 'zhejiangF4' and password == 'sb945':
                        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()
    多个装饰器
  • 相关阅读:
    【BZOJ4553】[Tjoi2016&Heoi2016]序列 cdq分治+树状数组
    【BZOJ4556】[Tjoi2016&Heoi2016]字符串 后缀数组+二分+主席树+RMQ
    【BZOJ4559】[JLoi2016]成绩比较 动态规划+容斥+组合数学
    STM32L476应用开发之七:流量的PID控制
    STM32L476应用开发之六:电池SOC检测
    信息摘要算法之一:MD5算法解析及实现
    我的家乡
    STM32L476应用开发之五:数据保存与SD卡操作
    STM32L476应用开发之四:触摸屏驱动与数据交互
    STM32L476应用开发之三:串行通讯实验
  • 原文地址:https://www.cnblogs.com/bingabcd/p/6688374.html
Copyright © 2020-2023  润新知