zoukankan      html  css  js  c++  java
  • python学习笔记之装饰器(语法糖)

    • 什么是装饰器
    • 装饰器的知识点铺垫(函数即变量,高阶函数,嵌套函数)
    • 不带参数的装饰器示例
    • 带参数的装饰器示例
    • 作业

    一、什么是装饰器

    本质上,装饰器就是返回一个函数的高阶函数。装饰器就是一个函数

    装饰器的原则:

    • 不修改被装饰对象的源代码
    • 不修改被装饰对象的调用方式

    二、装饰器涉及的知识点

    • 函数即变量
    • 高阶函数
    • 嵌套函数

    函数即变量:

    在python中,一个变量首先被定义,分配内存空间,然后再使用。

    以x=1,这个简单的赋值语句为例子。首先在内存中分配一个空间,x指向该内存空间,该内存空间内存入“1”

    函数名本质也是一个变量,所以def test()这个语句执行后,就是在内存中分配一个空间,test指向该内存,该内存中存入函数体

    代码示例:

    #Author:Yueru Sun
    #函数即变量
    #示范一:
    def foo():
        print('in the foo')
    foo()
    #示范二:
    def bar():
        print('in the bar')
    def foo():
        print('in the foo')
        bar()
    foo()
    #示范三:
    #变量在使用的时候是先定义再使用
    def foo():
        print('in the foo')
        bar()
    def bar():
        print('in the bar')
    foo()
    #示范四:
    # def foo():
    #     print('in the foo')
    #     bar()
    #foo()#报错,因为此时bar还没有定义
    # def bar():
    #     print('in the bar')
    

    特别需要注意示例三是可以执行成功的,”示例三“=”示例二“

    因为在foo()执行,首先是def 了foo()和bar(),所以当执行到foo()的时候可以找到foo()和bar()

    示例四是不可以执行的。因为在foo()执行之前,bar还没有在内存中定义,找不到

    高阶函数:

    高阶函数就是满足函数当作参数被传递或者函数的返回值是函数

    嵌套函数:

    def f1():
        def f2():
            def f3():
                print('from f3')
            f3()
        f2()
    
    f1()
    f3() #报错,为何?请看下一小节
    

    还是从函数就是一个变量这个角度解释,因为f3()是在f1()内部定义的,相当于是”局部变量“,所以不能在函数外部访问到f3()

    三、不带参数的装饰器示例

    import time
    def timer(func): #timer(test1)  func=test1
        def deco(*args,**kwargs):
            start_time=time.time()
            func(*args,**kwargs)   #run test1()
            stop_time = time.time()
            print("the func run time  is %s" %(stop_time-start_time))
        return deco
    @timer  #test1=timer(test1)
    def test1():
        time.sleep(1)
        print('in the test1')
    test1()
    #执行结果:
    #in the test1
    #the func run time  is 1.0033304691314697

    上面的代码解释:

    函数timer最本质的作用就是返回一个deco,deco是一个函数的地址空间

    接下来需要理解的是@timer等价于:test1=timer(test1),timer(test1)执行之后就会返回deco,那执行test1就相当于执行了deco,即test1()=deco()

    所以test1()的结果是:

    in the test1
    the func run time  is 1.0033304691314697

    再来一个例子:

    Author:Yueru Sun
    import time
    def timmer(func):
        def wrapper(*args,**kwargs):
            start_time=time.time()
            func(*args,**kwargs)
            end_time=time.time()
            print('func 的 运行时间是:%s'%(end_time-start_time))
        return wrapper
    @timmer
    def test():
        time.sleep(2)
        print('test')
    test()
    @timmer
    def test1(number):
        time.sleep(1)
        print('func的第%s执行'%(number))
    test1(1)
    

     

    还是上面的理解过程,梳理一下执行过程:

    首先是定义了timer函数,接下来执行@timer就等价于执行test1=timer(test1),执行完返回了deco,那么test1(number)=deco(number)

    四、带参数的装饰器示例

    如果装饰器需要传入参数,那么就在上面的基础上再嵌套一次函数

    def timmer1(text):
        def out_wrapper(func):
            def wrapper(*args,**kwargs):
                start_time=time.time()
                func(*args,**kwargs)
                end_time=time.time()
                print('%s func 的运行时间是%s'%(text,end_time-start_time))
            return wrapper
        return out_wrapper
    @timmer1('sun')
    def test2():
        print('test2')
    test2()
    

    具体的理解不赘述了,可以复习一下这个文章:

    http://www.cnblogs.com/alex3714/articles/5765046.html

    五、作业

    编写装饰器,为多个函数加上认证的功能(用户的账号密码来源于文件),要求登录成功一次,后续的函数都无需再输入用户名和密码

  • 相关阅读:
    【转载】以太网帧类型速查表
    oracle 无法解析指定的连接标识符
    最近观影有感~
    myeclipse 8.5 安装svn插件
    Symbian S60 设备配置 IMAP
    VS 2008 自动缩进修改
    RGB YUV [转]
    NoteExpress 无法访问国外数据库
    小s坐月子
    2011124 code
  • 原文地址:https://www.cnblogs.com/mesunyueru/p/8969897.html
Copyright © 2011-2022 走看看