• python 装饰器


    写代码要遵循开发封闭原则,虽然在这个原则是用的面向对象开发,但是也适用于函数式编程,简单来说,它规定已经实现的功能代码不允许被修改,但可以被扩展,即:

    • 封闭:已实现的功能代码块
    • 开放:对扩展开发

    故装饰器的出现就是解决以上问题的

    一、什么是装饰器

      装饰器本质就是函数,功能是为其他函数附加功能

    二、装饰器遵循的原则

    1、不修改被修饰函数的源代码

    2、不修改被修饰函数的调用方式

    三、实现装饰器的知识储备

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

    装饰器的简单示例1:(在不修改源代码的基础上添加新的功能)

    import time
    def timmer(func):
        def wrapper():
            print(func)
            func()
        return wrapper
    @timmer#就相当于是装饰器的功能,将被装饰的index加入了新功能,即index=timmer(index)#
    def index():
        time.sleep(2)
        print("welcome to beijing")
    index()
    

    执行结果是:

    <function index at 0x000000000251B8C8>
    welcome to beijing
    

    装饰器示例2:(在不修改源代码的基础上添加计算运行时间的新的功能)

    # #计算运行时间
    import time#导入模块
    def timmer(func):#这时候相当于def timmer(func)是def timmer(index)
        def wrapper():
            print(func)  #打印index的内存地址
            start_time=time.time()#开始时间
            func()     #func()相当于index()#相当于执行index()原始函数
            stop_time=time.time()#结束时间
            print("run time is %s"%(stop_time-start_time))#第八步
        return wrapper#
    
    @timmer#是装饰器的功能,将被装饰的index加入了新功能,即index=timmer(index)
    def index():
        time.sleep(2)
        print("welcome to beijing")
    index()#由于上面def index()是def timmer(index)(),timmer(index)的执行结果是wrapper,
    # 故而执行index函数就相当于是执行wrapper()
    

    执行结果是:

    <function index at 0x00000000024CB8C8>
    welcome to beijing
    run time is 2.0001144409179688
    

    如图示例:

      

     

    什么叫高阶函数呢??

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

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

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

    高阶函数示例1:(函数接受的参数是一个函数名)

    def foo():
        print('from foo')
    def foo_1(func):
        print('from foo_1')
        func()
    
    def foo_2(func):
        print('from foo_2')
        return func
    foo_1(foo)#将函数名foo当做参数
    foo_2(foo)#将函数名foo当做参数
    

     执行结果是:

    from foo_1
    from foo
    from foo_2
    

     高阶函数示例2:(函数的返回值是一个函数名)

    def foo():
        print('from foo')
    def foo_1(func):
        print('from foo_1')
        func()
        return func
    foo=foo_1(foo)
    print(foo)
    

    执行结果是:

    from foo_1
    from foo
    <function foo at 0x0000000001D13E18>
    

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

    装饰器:

    无参装饰器:

    示例1:

    import time
    def timmer(func):
        def wrapper(*args,**kwargs):
            print(func)#打印的是home的内存地址
            start=time.time()
            func(*args,**kwargs)#由于func为home,故而返回下面执行home函数,即home(“xuyuanyuan”)
            stop=time.time()
            print('run time is %s ' %(stop-start))
        return wrapper
    
    @timmer#相当于home=timmer(home)
    def home(name):
        time.sleep(2)
        print('welcome to %s home page' %name)
    home('xuyuanyuan')#执行的是wrapper(“xuyuanyuan”),将xuyuanyuan当做参数传给wrapper(*args,**kwargs)这个函数
    

    执行结果是:

    <function home at 0x000000000254B8C8>
    welcome to xuyuanyuan home page
    run time is 2.0011146068573 
    

    示例2:

    ##无参装饰器(有参函数)
    import time
    def timmer(func):
        def wrapper(*args,**kwargs):#wrapper('egon','123')
            start_time=time.time()
            func(*args,**kwargs) #相当于执行该auth('egon','123')函数,将egon 123当做参数传给函数auth(name,password),故而输出print('egon','123')
            stop_time=time.time()
            print('run time is %s' %(stop_time-start_time))
        return wrapper
    
    @timmer  #auth=timmer(auth)
    def auth(name,password):
        print(name,password)
    auth('egon','123') #wrapper('egon','123')
    

     执行结果是:

    egon 123
    run time is 0.0
    

    示例3:

    ##判断最大值,并输出它的运行时间
    import time
    def timmer(func):#相当于def timmer(my_max)
        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#my_max=timmer(my_max)
    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)
    

    执行结果是:

    my_max function
    run time is 0.0
    =====> 2
    

      

    有参装饰器(即2层闭包函数)

    示例:

    def auth2(auth_type):
        def auth(func):
            # print(auth_type)
            def wrapper(*args,**kwargs):
                if auth_type == 'file':
                    with open("file.txt", mode="r", encoding="utf8") as f:
                        file_list = f.readlines()
                    name=input('用户名: ')
                    passwd=input('密码:')
                    if name in file_list:  # 如果用户名在黑名单内
                        print("您的账户已锁定,请联系管理员!")
    
                    if name == 'xyy' and passwd == '123':
                        print('auth successfull')
                        res=func(*args,**kwargs)#执行函数index()
                        return res
                    else:
                        print('auth error')
                elif auth_type == 'sql':
                    print('暂不支持')
            return wrapper
        return auth
    
    @auth2(auth_type='file') #auth2(auth_type='sql')的返回结果是author,故而@auth 相当于#index=auth(index)
    def index():
        print('welcome to inex page')
    index()#运行函数index
    

    执行结果是:

    用户名: xyy
    密码:123
    auth successfull
    welcome to inex page
    

    多个装饰器的使用:

    当需要使用多个装饰器的功能时,一般是先调用下面的@,再执行上面的@

    举例说明:(给上述例子加入计算运行时间的功能)

    import time#导入时间模块
    current_login={'name':None,'login':False}
    
    ##定义运行时间函数
    def timmer(func):
        def wrapper(*args,**kwargs):
            start_time=time.time()
            res=func(*args,**kwargs)
            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 == 'xyy' 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
    ##调用了2个装饰器,先执行@auth2(auth_type='file')再运行@timmer,由上至下
    @timmer##再执行这个
    @auth2(auth_type='file') #@auth  #index=auth(index)##先执行这个
    def index():
        print('welcome to inex page')
    index()
    

    执行结果是:

    username: xyy
    password: 123
    auth successfull
    welcome to inex page
    run time is 12.809732437133789
    welcome to inex page
    run time is 0.0
  • 相关阅读:
    两个简单的画验证码图形程序
    Cisco路由技术基础知识详解
    网络管理中的常用命令
    网络管理中的常用命令
    基于SNMP的MIB库访问实现
    SNMP编程基础
    SNMP编程基础
    Cisco路由技术基础知识详解
    两个简单的画验证码图形程序
    模版方法
  • 原文地址:https://www.cnblogs.com/xuyuanyuan123/p/6690218.html
Copyright © 2020-2023  润新知