函数 -- 闭包

函数引用
def test1():
    print("--- in test1 func----")

ret = test1  # 获得函数引用

print( type(ret) )
print( id(ret) )
ret()  # 使用函数引用调用函数

140212571149040
--- in test1 func----

函数名中保存着函数的入口地址,将函数名赋给变量,该变量中也保存了函数地址,称为函数引用,可以使用变量()的形式调用函数

闭包

在函数内部再定义一个函数,并且内部函数用到了外部函数的变量,那么将这个内部函数以及用到的变量称之为闭包

def 函数名():
    局部变量...
    def 内部函数名():
        pass
    return 内部函数名
  • 应用场景1
def func(n):
    def func_in(n_in):
        print("in func_in 函数, n_in is %d" % n_in)
        return n + n_in

    return func_in
ret = func(20)
  • 调用func函数,从返回值中获得func_in函数的引用,并赋值给变量ret
  • 数字 20 传递给func函数的形参 n
ret(100)
  • 因为变量retfunc_in函数的引用,所以ret(100)相当于func_in(100)
  • 数字100赋值给func_in函数的形参n_in
print( ret(100) )
120
  • 输出func_in函数的结果
  • 其中n赋值为20n_in赋值为100,所以结果为120
  • 应用场景2
def line_conf(a, b):
    def line(x):
        return a*x + b
    return line

line1 = line_conf(1, 1)
line2 = line_conf(4, 5)
print(line1(5))
print(line2(5))


6
25
  • 函数line与变量a、b构成闭包
  • 通过为line_conf的参数 ab 赋值,可以确定函数的形式为 y = x + 1y = 4x + 5
  • 之后只要变换参数a、b,就可以获得不同的直线函数,并根据x计算对应的y
  • 如果没有闭包,每次创建直线函数时都要同时说明a、b、x的值,就要传递更多的参数,增加了代码移植的难度
  • 修改外部函数中的变量
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())

print(c1())
print(c1())

print(c2())
print(c2())


6
7
51
52
8
9
53
54
  • 内部函数使用全局变量(函数最外层的变量),用global声明
  • 内部函数使用外部函数的局部变量(内部函数外,外部函数内的变量),用nonlocal声明




- end -

你可能感兴趣的:(函数 -- 闭包)