zoukankan      html  css  js  c++  java
  • Python学习————装饰器

    一、有参装饰器

    无参装饰器的用法,模板如下:

    def outter(func):#参数写死,为了给语法糖传值
       def warpper(*args,**kwargs):#参数写死,为了给func传值
           res = func(*args,**kwargs)
           return res
       return warpper
    @outter
    def index():
       print("这是主页")
       return 1
    res = index()
    print(res)
    
    >>>这是主页
    >>>1
    >>>从这段模板代码我们可以看出,装饰器的两个函数我们都无法为它增加新的参数传值
    

    所以,当我们的装饰器需要跟多参数的时候,就只能通过闭包函数为他传值

    2 如何使用有参装饰器

    下面通过一个需求来表现有参装饰器的用途:

    例:编写装饰器对多个函数添加认证功能,如果登录成功过,其他函数就不需要再次登录

    分析需求:我们要编写认证功能的话只要添加个简单的有判断的装饰器即可,但是要判断之前是否成功过,我们就需要用到全局变量,如果登录成功把全局变量修改即可。所以我们在装饰器内部就要再判断一下,这个全局变量的值是什么,这里就会出现矛盾

    我们要先判断全局变量,如果没有登录过,就修改他的值,这里违背了变量的先定义后引用的原则

    所以基于这个矛盾,我们需要对装饰器传值,而在上面模板中我们已经知道,装饰器的函数我们都无法为他传值,因为各有用途都写死了。所以我们只能用第二种传值方式:闭包

    is_login = True
    def auth(login):
        def outter(func):
            def warpper(*args,**kwargs):
                if login:
                    name = input("你的名字:")
                    pwd = input("你的密码:")
                    if name == "hz" and pwd == "123":
                        print("登录成功")
                        func(*args,**kwargs)
                        global is_login
                        is_login=False
                    else:
                        print("输入错误")
                else:
                    func(*args,**kwargs)
            return warpper
        return outter
    #语法糖的定义:被装饰函数 = @后面的东西(被装饰的函数)
    #index = auth(is_login)(index)
    #auth(is_login) == outter
    #outter(index) ==warpper
    @auth(is_login)
    def index():
        print("你好")
    index()
    @auth(is_login)
    def home():
        print("欢迎回家")
    home()
    

    3 有参装饰器模板

    def 有参装饰器(x,y,z):
        def outter(func):
            def wrapper(*args, **kwargs):
                res = func(*args, **kwargs)
                return res
            return wrapper
        return outter
    @有参装饰器(1,y=2,z=3)
    def 被装饰对象():
        pass
    

    4 修正装饰器

    我们的装饰器最终目的就是要把(原函数+装饰器)修改成和没有修改的函数一样(属性上)

    但是,我们之前的学习装饰器还没有完成最终目的

    @timer
    def home(name):
        '''
        home page function
        :param name: str
        :return: None
        '''
        time.sleep(5)
        print('Welcome to the home page',name)
    
    print(help(home))
    '''
    打印结果:
    
    Help on function wrapper in module __main__:
    
    wrapper(*args, **kwargs)
    
    None
    

    每个函数在定义出来后就有非常多的属性,名字,注释等等,我们如果一一修改就非常麻烦,这里可以用functools模块下提供的一个装饰器wraps专门用来帮我们实现这个:

    from functools import wraps
    def timer(func):
        @wraps(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
    
  • 相关阅读:
    .NET微服务调查结果
    发布基于Orchard Core的友浩达科技官网
    Followme Devops实践之路
    积极参与开源项目,促进.NET Core生态社区发展
    Service Fabric 与 Ocelot 集成
    “.Net 社区大会”(dotnetConf) 2018 Day 1 主题演讲
    Project file is incomplete. Expected imports are missing 错误解决方案
    稳定工作和创业之间的抉择
    回顾4180天在腾讯使用C#的历程,开启新的征途
    ML-Framework:ML.NET 0.3 带来新组件
  • 原文地址:https://www.cnblogs.com/x945669/p/12562151.html
Copyright © 2011-2022 走看看