内部函数:
今天在学习python的时候发现了一个神奇的功能,python居然能在函数内声明函数。
def func():
n = 100
list1 = [3,6,9,4]
def inner_func():
# 让每一个元素都 + 5
for index,i in enumerate(list1):
list1[index] = i + 5
list1.sort()
print(list1)
func()
# [8, 9, 11, 14]
内置函数可以在函数内部执行。内部函数可以访问外部的变量。
def func():
n = 100
list1 = [3,6,9,4]
def inner_func():
list1.append(5)
nonlocal n
n = 3
print(n)
print(list1)
inner_func()
func()
# 3
# [3, 6, 9, 4, 5]
内部函数可以修改外部可变类型的变量。不可变变量要声明才能修改,比如说n,这个机制跟全局变量有点相似。但是要加nonlocal。
闭包:
条件:
1.外部函数中定义了内部函数
2.外部函数是有返回值的
3.返回值是内部函数名
4.内部函数引用了外部函数的变量值
def func():
a = 100
def inner_func():
b = 99
print(a,b)
return inner_func
x = func()
x()
# 100 99
闭包就是把一个内部的函数作为返回值,用x接收之后x就相当于inner_func,如果想调用inner_func的话就直接用x()调用就行了。闭包的好处是提供了访问局部变量的机会。
def func(a,b):
c = 10
s = 0
def inner_func():
nonlocal s
s += a + b + c
print(s)
return inner_func
x = func(1,2)
x()
# 13
x()
# 26
y = x
y()
# 39
y = func(1,2)
y()
# 13
这段代码中,在x被赋值为inner_func之后里面的具体变量也被赋值,这个返回值inner_func相当于是一种状态的记录。再次调用被赋值的变量(注意,这里的被赋值指的是x而不是func,代码中重新定义一个y = func(1,2)时,就会重新开辟一片func新的区域)使用的还是同一片内存地址,此时闭包函数对外部函数中变量的改变仍然有效。
func的返回值相当于调用之后开辟一片新的地址加载数据并处理,这点如果学过c++的话十分容易理解,和c++递归函数的机制差不多的。
闭包的缺点:
1.作用域没那么直观。
2.因为变量不会被垃圾回收所以有一定的内存占用问题。
闭包的作用:
1.可以使用同级的作用域。
2.读取其他元素的内部变量。
3.延长作用域。
闭包总结:
1.闭包优化了变量,原来需要类对象完成的工作,闭包也可以完成。
2.由于闭包引用了外部函数的局部变量,则外部函数的局部变量没有及时释放,消耗内存。
3.闭包的好处,使代码变得简洁,便于阅读代码。
4.闭包是理解装饰器的基础。