美文网首页
从python中闭包到装饰器

从python中闭包到装饰器

作者: _icey_ | 来源:发表于2021-07-06 19:05 被阅读0次

    一、闭包

    首先要明确自由变量的含义。自由变量是指在函数中使用,但是并非在此函数中被定义的变量。

    闭包不同于其他函数是因为,闭包使用了自由变量,并且闭包中的自由变量在脱离了定义该自由变量的上下文后,依然可以被正常使用。

    也就是百度百科上讲的闭包是能够读取其他函数内部变量的函数,即函数+函数内部能访问到的变量的总和就是一个闭包

    上代码:

    def outer(a):
        c = 1  # outer作用域中定义的变量c
        def inner(b):
            print("inner函数传进来的数字是:", b)
            return a + b + c  # inner函数能够读取到a和c的值
        return inner
    
    result = outer(2)
    print(result)  # 返回的是inner函数
    print("闭包返回结果:", result(3)) # 这里的结果是 1+2+3 的值
    

    在上述代码中inner函数与变量a和c构成一个闭包。


    运行结果.png

    二、装饰器

    python中的装饰器就是对闭包很好的应用。装饰器顾名思义就是可以给已有函数增加其他功能,而不改动函数本身的代码,这样的做法可以让编程的过程变得更加的灵活,查阅python源码也可以看到很多装饰器的使用

    装饰器本身是一个闭包,只是将外部函数的变量名变成了一个函数

    装饰器的构成:
    函数+实参高阶函数+返回值高阶函数+嵌套函数+语法糖

    • 实参高阶函数:把一个函数名当做实参传给另一个函数

    • 返回值高阶参数:返回值中包含函数名

    装饰器的执行顺序是先执行装饰器里的方法,然后再执行被装饰函数的代码

    上代码:

    1. 被装饰的函数不带参数:

    import time
    def timefun(func):
        def inner():
            start = time.time()
            func()
            end = time.time()
            print(func.__name__,"函数运行时间为",end-start)  # 用函数对象的__name__属性,可以得到函数的名字
        return  inner
    
    @timefun
    def f():
        time.sleep(2)
        print("我现在被执行了")
    
    f()
    
    运行结果

    这个timefun装饰器的作用非常简单,是为被装饰的函数添加程序运行时间的计时功能,此段程序的运行过程是:函数f作为参数被传入到装饰器timefun中,返回inner函数,再进行调用,现在timefun的效果已经加到函数f上面了。

    以后再为其他函数添加计时功能,直接使用timefun装饰器即可,不需要重新写一遍计时的代码。

    2. 被装饰的函数带返回值:

    对于被装饰函数带返回值的情况,则需要在内层函数中使用变量接收,再将其返回出来


    被装饰函数带返回值.png

    3. 被装饰的函数有参数:

    如果被装饰函数中需要参数传递,则需要在内层函数中留接收的位置

    import time
    
    
    def timefun(func):
        def inner(a):
            start = time.time()
            res = func(a)
            end = time.time()
            print(func.__name__,"函数运行时间为",end-start)  # 用函数对象的__name__属性,可以得到函数的名字
            return res
        return inner
    
    
    @timefun
    def f(a):
        time.sleep(2)
        print("我现在被执行了")
        return "我是返回值,我返回了参数{}".format(a)
    
    运行结果

    TIPS: 如果按照解包的方式传递参数,调用的时候参数也可以不填,代码如下

    import time
    
    
    def timefun(func):
       def inner(*args,**kwargs):
           start = time.time()
           res = func(args)
           end = time.time()
           print(func.__name__,"函数运行时间为",end-start)  # 用函数对象的__name__属性,可以得到函数的名字
           return res
       return inner
    
    
    @timefun
    def f(a):
       time.sleep(2)
       print("我现在被执行了")
       return "我是返回值,我返回了参数{}".format(a)
    

    4. 装饰器带参数

    如果要在装饰器装饰函数的时候向装饰器内部传值的话,则需要定义带参数的装饰器,定义的方式也非常简单,就是将之前的装饰器外层再嵌套一层函数,并且将第二层函数作为返回值返回,代码如下:

    import time
    
    def timefun(param):
        print(param)
        def outer(func):
            def inner(*args,**kwargs):
                start = time.time()
                res = func(args)
                end = time.time()
                print(func.__name__,"函数运行时间为",end-start)  # 用函数对象的__name__属性,可以得到函数的名字
                return res
            return inner
    
        return outer
    
    @timefun("f函数中使用的")
    def f(a):
        time.sleep(2)
        print("我现在被执行了")
        return "我是返回值,我返回了参数{}".format(a)
    
    print(f())
    print("---------------------分割线------------------------")
    @timefun("g函数中使用的")
    def g(a):
        time.sleep(2)
        print("我现在被执行了")
        return "我是返回值,我返回了参数{}".format(a)
    print(g())
    
    运行结果.png

    相关文章

      网友评论

          本文标题:从python中闭包到装饰器

          本文链接:https://www.haomeiwen.com/subject/fhkgultx.html