1. 高阶函数:由于python中一切皆对象,变量是对象,函数也是对象,函数也能像变量那样进行传递。一个函数可以作为参数传给另外一个函数,或者
一个函数的返回值为另外一个函数(若返回值为该函数本身,则为递归),满足其一则为高阶函数。
函数名是函数对象的引用,即函数名也是变量,函数名后面加上()就是表示执行函数。
1)函数作为参数
def bar(): print("in the bar..") def foo(func): func() print("in the foo..") foo(bar)
2)返回值为函数
def bar(): print("in the bar..") def foo(func): print("in the foo..") return bar res = foo(bar) res()
2. 函数嵌套:在一个函数中定义了另外一个函数,当外部函数被调用的时候,内部函数都会被重新定义,如果内部函数不被返回,则外部函数执行结束后,
内部函数对象就会被销毁。下面举一个简单的例子:
def test1(): age = 10 print(age) def test2(): te = 5 print(age) def test3(): print(te) test3() test2() test1() # 10 10 5
注:由于每次内部嵌套函数都会重新定义,所以对于频繁使用的函数是不建议其内部定义嵌套函数的,否则效率低。
3. 闭包:在一个外函数中定义了一个内函数,内函数里运用了外函数的临时变量,并且外函数的返回值是内函数的引用。这样就构成了一个闭包。
所以闭包是既符合高阶函数,又满足嵌套函数。
一般情况下,在我们认知当中,如果一个函数结束,函数的内部所有东西都会释放掉,还给内存,局部变量都会消失。但是闭包是一种特殊情况,
如果外函数在结束的时候发现有自己的临时变量将来会在内部函数中用到,就把这个临时变量绑定给了内部函数,然后自己再结束。
def outer(a): b = 10 # a 和 b 都是外函数的临时变量 def inner(): a = a * 2 print(a + b) # 在内函数中用到了外函数的临时变量 return inner # 外函数的返回值是内函数的引用 # 调用外函数传入参数5 # 此时外函数两个临时变量 a = 5 b = 10 ,并创建了内函数,然后把内函数的引用返回存给了 demo # 外函数结束的时候发现内部函数将会用到自己的临时变量,这两个临时变量就不会释放,会绑定给这个内部函数 demo = outer(5) demo() # 15 demo2 = outer(7) demo2() # 17
闭包中内函数修改外函数局部变量:
- 在闭包内函数中,我们可以随意使用外函数绑定来的临时变量,但是如果我们想修改外函数临时变量数值的时候发现出问题了!
- 在基本的python语法当中,一个函数可以随意读取全局数据,但是要修改全局数据的时候有两种方法:
1) global 声明全局变量,否则赋值操作是重新定义一个变量
2)全局变量是可变类型数据的时候可以修改
- 在闭包内函数也是类似的情况。在内函数中想修改闭包变量(外函数绑定给内函数的局部变量)的时候:
1)在python3中,可以用 nonlocal 关键字声明一个变量, 表示这个变量不是局部变量空间的变量,需要向上一层变量空间找这个变量。
2)在python2中,没有 nonlocal 这个关键字,我们可以把闭包变量改成可变类型数据进行修改,比如列表。
def outer(a): b = 10 c = [a] def inner(): nonlocal b # 这样就可以修改闭包变量 b 了 b += 1 c[0] += 1 # 通过可变类型对象也可以实现修改 print(c[0]) print(b) return inner demo = outer(5) demo() # 6 11