zoukankan      html  css  js  c++  java
  • 攻克python3-装饰器

    装饰器

    1.为什么要使用装饰器?

    在产品升级中,有成千上百个函数,要为这些函数增加某些功能,如果一个个函数的修改,岂不是浪费资源,浪费时间,这是装饰器的好处就展现了,它可以在短时间内完成你对许多函数的修改。

    2.什么是装饰器?

    装饰器也是函数,是装饰其他函数的函数(为其他函数增加功能)

    3.装饰器的原则:

      a.不能修改原函数的代码

      b.不改变原函数的调用方式

    4.装饰器的知识储备:

      a.函数即“变量”

      b.高阶函数

      c.嵌套函数

    a.函数即“变量”

    在定义函数时,系统将函数体内的函数过程作为字符串保存在内存中,当作一个变量储存,只是把地址赋给了函数名,在调用函数时,再去解释函数过程

    b.高阶函数

    1.一个函数的函数名作为另一个函数的参数

    import time
    def bar():
        time.sleep(2)
        print("in the bar")
    
    def test1(func):
        start_time=time.time()
        func()
        stop_time=time.time()
        print("the test run time is %s"%(stop_time-start_time))
    
    
    bar()
    print("-----------")
    test1(bar)

    通过上面的演示是不是得出一个结论:高阶函数可以在不改变原函数的源代码的情况下,为其增加功能,但会改变原函数的调用方式

    2.一个函数的返回值包括函数名

    import time
    def bar():
        time.sleep(2)
        print("in the bar")
    
    
    def test1(func):
        start_time=time.time()
        func()
        stop_time=time.time()
        print("the test run time is %s" % (stop_time - start_time))
        return func
    
    
    bar=test1(bar)
    print("------")
    bar()

    通过上面的演示是不是得出一个结论:高阶函数可以不改变原函数的调用方式,但是没有添加新功能

    c.嵌套函数

    def foo():
        print("in the foo")
        def bar():
            print("in the bar")
        bar()
    
    foo()

    5.写装饰器

    a.装饰器是为给其他函数增加功能,但是不能改变原函数的源代码,那我们怎么才能不改变原函数的源代码,回顾上文,通过高阶函数(将函数名作为另一个函数的参数)定义一个新函数,在新函数中调用原函数,并且添加新功能,这样就可以实现我们的目标

    #现在我有一个函数tets1,然后为它添加一个新功能
    def dec(func):
        print("我是新功能!")
        func()
    
    def test1():
        print("in the test1")
    
    test1()
    print("-------")
    dec(test1)

    b.在不修改原函数的同时,而且也不能修改函数的调用方式,函数的调用方式是不是函数名(),那么函数即“变量”,在这里就起大作用了,在上面代码中,我们可以将新函数的函数地址赋给原函数的函数名,原函数的函数名对应的内存空间发生了改变,这片新的内存空间中既有原函数的功能,也有新增加的功能,那么我们通过高阶函数(返回值中包含函数名)将原函数的函数名重新赋值,这样我们的目的就达到了。

    #因为需要返回新函数的函数名(函数地址),所以要使用嵌套函数
    def foo(func):             #func=test1  将test1函数地址传给了func   所以新函数的内存空间保存了原函数的内存地址,可以通过调用新函数来调用原函数,并且增加功能
        def dec():
            print("我是新功能!")
            func()
        return dec
    
    @foo    #相当于test1=foo(test1)    在python中 装饰器 用@装饰圈名 来表示
    def test1():
        print("in the test1")
    
    test1()
    print("-------")
    #test1=foo(test1)
    test1()

    6.高级版装饰器

    import time
    def
    timer(func): #func=test1 将test1的地址赋给func def deco(*args,**kwargs): start_time = time.time() res=func(*args,**kwargs) #相当于调用test1 stop_time=time.time() print("the func run time is %s" % (stop_time - start_time))
         return res
    return deco #将deco的地址返回 @timer #相当于test1=timer(test1) def test1(): time.sleep(2) print("in the test1") @timer def test2(name): time.sleep(2) print("in the test2",name) return name # test1=timer(test1) #test1=deco 将deco的地址赋给test1 test1() #相当于调用deco test2("phk")

    以上代码中,装饰器的功能是为两个函数增加计时功能,与之前有所不同的是,原函数中是带参数和返回值,那么我们可以使用*args **kwargs来充当函数参数,与参数一样,我们给新函数定义返回值,这样就做到了透明化处理.

    7.高潮版

    user,passwd="phk","123"
    
    def auth(auth_type):
        #print(auth_type)
        def outer(func):
            #print(func)
            def deco(*args,**kwargs):
                if auth_type == "local":
                    username=input("usernane:").strip()
                    password=input("password:").strip()
                    if user==username and passwd==password:
                        func()
                    else:
                        exit("账号密码错误")
                elif auth_type=="ldap":
                    print("不会")
            return deco
        return outer
    
    def index():
        print("welcome to index page")
    
    @auth(auth_type="local")            #相当于home=auth(auyh_type="local")(func)
    def home():
        print("welcome to home page")
    
    @auth(auth_type="ldap")
    def bbs():
        print("welcome to bbs page")
    
    index()
    home()
    bbs()

    装饰器的功能是为三个页面函数添加登陆功能,不同的是需要选择本地登陆还是ldap登陆,说白了就是在装饰器外面在套一层函数,传进来的参数可以作为局部参数,可以咱函数体内使用,但是需要明白一点

     @auth(auth_type="local") 相当于home=auth(auyh_type="local")(func)。

     解释器会先翻译“auth(auth_type = 'local')”,再将其返回值(假设给了_func这个不存在的函数名)当作函数指针,这里的_func函数名代表的是outer,然后再去执行“func = _func(func)”,而这个func函数名代表的其实就是deco。

  • 相关阅读:
    Delphi的idhttp报508 Loop Detected错误的原因
    Delphi的idhttp报IOHandler value is not valid错误的原因
    华为S5700S-52P-LI-AC千兆网管交换机web登录界面配置
    解决win2003/2008下注册机或破解补丁程序无法运行问题
    SQL拆分(转)
    1602四线驱动
    ADC取样
    Delphi AES加密(转)
    使用Qt开发中国象棋(一):概述
    清除当前文件夹下.svn文件的方法
  • 原文地址:https://www.cnblogs.com/kxsph/p/8930344.html
Copyright © 2011-2022 走看看