Python 中的闭包 和 装饰器

闭包


    1.闭包的概念及三要素:

        闭包其实就是一种代码的实现方式

        闭包的三要素:1. 函数的嵌套 ; 2.内层函数使用外层函数的变量  ;3.外层函数返回内层函数的引用

        举例如下:

# 定义一个外部函数
def test(number):

    # 在函数内部再定义一个函数,并且这个函数用到了外边函数的变量,那么将这个函数以及用到的一些变量称之为闭包
    def test_in(number_in):
        print("in test_in 函数, number_in is %d" % number_in)
        return number+number_in
    # 其实这里返回的就是闭包的结果
    return test_in


# 给test函数赋值,这个20就是给参数number
ret = test(20)

# 注意这里的100其实给参数number_in
print(ret(100))

#注 意这里的200其实给参数number_in
print(ret(200))

运行结果如下:

in test_in 函数, number_in is 100
120

in test_in 函数, number_in is 200
220

    2.修改闭包中外部函数的变量

        在闭包内部需要使用nonlocal 关键字 来修改外部函数的变量

def counter(start=0):
    def incr():
        nonlocal start
        start += 1
        return start
    return incr

c1 = counter(5)
print(c1())
print(c1())

c2 = counter(50)
print(c2())
print(c2())

    运行结果是:

6
7
51
52

    备注: 经典面试题

def func(a):
    def call_func(x):
        return a * x

    return call_func


flist = [func(a) for a in range(3)] # 闭包中的三个函数分别是独立的空间 ,变量a的值均不同
print(flist[0](1))
print(flist[1](1))
print(flist[2](1))
print("*" * 30)
flist = [lambda x: a * x for a in range(3)] # 匿名函数方式中变量a指向是一致的,导致a的值被覆盖,最后结果全部是2
print(flist[0](1)) 
print(flist[1](1))
print(flist[2](1))


# 运行结果如下:

0
1
2
******************************
2
2
2

装饰器(重难点)

    1.作为Python面试中必问到的关键点---装饰器,程序开发中用的好,开发如虎添翼; 主要运用在 不能对被修饰的函数源代码进行修改, 和调用方式进行更改的情况下, 为函数添加其他功能;

    2.装饰器主要的作用如下:

  1. 引入日志
  2. 函数执行时间统计
  3. 执行函数前预备处理
  4. 执行函数后清理功能
  5. 权限校验等场景
  6. 缓存

    3.装饰器大致流程如下:

        1.执行外部函数, 原函数作为参数传递给到外层函数的形参

        2.定义一个内层函数, 并且内层函数使用外层函数的变量,并调用传递进来的原函数的引用

        3.外层函数的返回内层函数的引用,且调用内层函数

    4.被装饰器修饰的函数或者方法,可以是无参数的, 有参数的,不定参数的, 也可以是有返回值的, 也可以是无返回值的,也可以用作类装饰器(当然这个资源消耗较高,不建议使用), 装饰器大致的模板如下:

def set_func(func):
    print("开始准备装饰器...")
    def call_func(*args, **kwargs): # 这个地方的参数的可以是无参数,有参数,以及不定长参数
        print("执行装饰器内部方法...")
        return func(*args, **kwargs)# 这个地方的*代表的是拆包, 传递的元祖,字典内容到func方法中的,而不是元祖和字典两个参数

    return call_func


@set_func  # 相当于 test = set_func(test)
def test():
    print("test")


test()

#运行结果:
#开始准备装饰器...
#执行装饰器内部方法...
#test

    5.多个装饰器修饰一个函数的情况, 是以就近原则的, 先调用靠近原函数的外部函数,后执行靠近函数的内部函数,如下例:

def set_func_1(func):
    print("开始准备装饰器1...")

    def call_func(*args, **kwargs):
        print("执行装饰器内部方法1...")
        return func(*args, **kwargs)

    return call_func


def set_func_2(func):
    print("开始准备装饰器2...")

    def call_func(*args, **kwargs):
        print("执行装饰器内部方法2...")
        return func(*args, **kwargs)

    return call_func


@set_func_1
@set_func_2
def test():
    print("test")


test()

#运行结果:
#开始准备装饰器2...
#开始准备装饰器1...
#执行装饰器内部方法1...
#执行装饰器内部方法2...
#test

6.带参数的装饰器的流程:

    大三步:

        [1].调用最外层函数,并将装饰器中的参数传递给最外层函数;

        [2].定义一个中层函数;

        [3].返回中层函数,并用这个中层函数装饰原函数----其中还有个小三步:如下:

                    a.调用中层函数,并将原函数作为参数传递给中层函数

                    b.定义一个内层函数;在内层函数中调用中层函数变量,并调用了原函数

                    c.中层函数返回内层函数的引用,并调用内层ha


def set_level(level_num):
    print("执行外层函数装饰")

    def set_func(func):
        print("执行中层函数装饰")

        def call_func(*args, **kwargs):
            print("执行内层函数")
            return func(*args, **kwargs)

        return call_func

    return set_func


@set_level(2) 
def test():
    print("--test--")


test()

运行结果:

执行外层函数装饰
执行中层函数装饰
执行内层函数

--test--




猜你喜欢

转载自blog.csdn.net/weixin_42225318/article/details/80635430