【Python】函数闭包与装饰器

文章目录

  • 闭包
  • 装饰器

要理解python的装饰器的前提是要了解python的函数闭包,什么是函数闭包呢?简单来说就是函数里定义和调用函数。

这是一个两层装饰的装饰器

def decorator1(fun):
    print('decorator1')
    def in_decorator1():
        print('in_decorator1')
        def inner1():
            print('inner1')
            def inner2():
                print('inner2')
                return fun
            return inner2()
        return inner1()
    return in_decorator1()


def decorator2(fun):
    print('decorator2')
    def in_decorator2():
        print('in_decorator2')
        def inner2_1():
            print('inner2_1')
            def inner2_2():
                print('inner2_2')
                return fun
            return inner2_2()
        return inner2_1()
    return in_decorator2()

@decorator2
@decorator1
def fun():
    print('in fun')


if __name__ == "__main__":
    fun()

执行结果如下

decorator1
in_decorator1
inner1
inner2
decorator2
in_decorator2
inner2_1
inner2_2
in fun

闭包

在没有理解python的函数闭包之前我是不能理解上面那段代码的执行过程的,先来看看python的闭包,
这段代码很简单,输出变量a的值10。

def fun():
    a = 10
    print(a)

if __name__ == "__main__":
    fun()

我们知道python中在函数中定义的变量只能在函数中使用而不会被函数外的其他方法调用。

def fun():
    a = 10
    print(a)

print(a)

不出意外运行报错,a没有被定义。
报错

那么在函数中定义函数又是怎么样的呢?
这段代码会输出变量a的值,这说明了在函数fun()中定义的变量可以在fun()函数中的函数in_fun()中使用。

def fun():
    a = 10
    def in_fun():
        print(a)
    return in_fun()

if __name__ == "__main__":
    fun()

pic

如果改成下面这样会看不到执行结果,仔细一看会发现,调用fun()的时候,in_fun()这个函数并没被调用,只是被定义。

def fun():
    a = 10
    def in_fun():
        print(a)

if __name__ == "__main__":
    fun()

所以我们必须在函数fun()调用时在fun()函数中调用其子函数,否则就不会执行子函数而仅仅只是被定义。

def fun():
    a = 10
    def in_fun():
        print(a)
    in_fun()

if __name__ == "__main__":
    fun()

pic

在fun()中定义的变量,fun()的子函数都能使用这个变量,就像在类中定义一个变量,其子类、子类的子类都能使用这个变量一样。

def fun():
    a = 10
    def in_fun1():
        b = 20
        def in_fun2():
            print(a)
            print(b)
        in_fun2()
    in_fun1()


if __name__ == "__main__":
    fun()

pic

一个完整的闭包就是函数中定义变量并且在函数中定义函数,在函数中使用函数,层层嵌套,使无限套娃成为了可能,但是要记住套娃有风险,必须要在上一层完成对下一层的调用,下面这段代码由于直接在fun()中调用in_fun2(),没有调用in_fun1(),所以调用的是一个没有定义的in_fun2()。

def fun():
    a = 10
    def in_fun1():
        b = 20
        def in_fun2():
            c = 30
            print(a)
            print(b)
        
    in_fun2()


if __name__ == "__main__":
    fun()

【Python】函数闭包与装饰器_第1张图片

只要上一层完成对下一层函数的调用,就可以无限套娃了,这就是函数的闭包。

def fun():
    a = 10
    def in_fun1():
        b = 20
        def in_fun2():
            c = 30
            def in_fun3():
                d = 40
                def in_fun4():
                    e = 50
                    print(a+b+c+d+e)
                    return 0
                return in_fun4()
            return in_fun3()
        return in_fun2()
    return in_fun1()
  

if __name__ == "__main__":
    fun()

pic

装饰器

装饰器就是为了在不改变原函数的基础上扩展程序而出现的python语法糖,菜鸟教程中写得非常好,通俗易懂。

以一层的装饰器来说,主要注意的是最里面的一层,return fun返回的是函数的引用而不是返回函数的调用,因为我们的最终的目的不是执行fun()这个函数,而是在执行这个函数之前对其做装饰。

def decorator1(fun):
    print('decorator1')
    def in_decorator1():
        print('in_decorator1')
        def inner1():
            print('inner1')
            def inner2():
                print('inner2')
                return fun
            return inner2()
        return inner1()
    return in_decorator1()

@decorator1
def fun():
    print('in fun')


if __name__ == "__main__":
    fun()

【Python】函数闭包与装饰器_第2张图片

你可能感兴趣的:(Python,python,装饰器,闭包,属性,函数依赖)