一、嵌套函数
1、内部函数
内部函数的特点:
可以访问外部函数的变量们
内部函数可以对外部函数的可变类型的变量进行修改,比如list1
def func():
n=100
list1=[3,6,9,4]
#声明内部函数
def inner_func():
#对list1里面的每个数进行加5操作,用到枚举
for index,i in enumerate(list1):
list1[index] = i+5
list1.sort()
#调用内部函数
inner_func()
print(list1)
#调用func
func()
结果为:
[8, 9, 11, 14]
注意:只定义了内部函数,还要在内部函数里面进行调用,不然不会出现结果
2、嵌套函数的变量访问
内部函数访问的时候,涉及到变量的范围,想要修改全局变量得加上global,修改局部变量要使用nolocal
a=100
def func():
b=99
def inner_func():
global a
nonlocal b
c=88
#尝试修改b
b+=1
c+=12
a+=2
#尝试打印a,b,c
print(a, b, c)
inner_func()
func()
结果为:
102 100 100
总结:
内部函数修改全局的不可变变量时,需要在内部函数声明global变量名;内部函数修改外部函数的不可变变量时,需要在内部函数中声明nolocal变量名。
3、locals和globals()
locals()可以看到在当前函数中,声明的内容有哪些
locals以字典的形式输出,key:value
globals()查看全局变量有哪些,里面会有一些系统的键值对
以上例为例
......
print(locals())
print(globals())
结果为:
{'inner_func': <function func.<locals>.inner_func at 0x000001DD9F736620>, 'b': 100}
{'__name__': '__main__', '__doc__': '\ndef func():...'a': 102, }
二、闭包
1、闭包初体验
闭包是在函数中提出的概念,在函数里面定义了一个内部函数,又把内部函数给扔rerurn出来了,这样格式的就叫闭包
形成闭包的条件:
1、在外部函数里定义了内部函数
2、外部函数是有返回值的
3、返回的值是:内部函数名
4、内部函数引用了外部函数的变量值,就是print(a,b)
def func():
a=100
def inner_func():
b=99
print(a,b)
return inner_func #外部函数的返回值
x=func()
#x就是内部函数,x()就是调用函数
x()
例子2
def func(a,b):
c=10
def inner_func():
s=a+b+c
print(f"相加之后的结果是:{s}")
return inner_func
#调用func
x=func(6,9)
#x就是inner_func,调用返出来的内部函数
x()
结果为:
相加之后的结果是:25
2、闭包同级访问
def func():
a=100
def inner_func1():
b=90
s=a+b
print(s)
def inner_func2():
inner_func1()
print("--->inner_func2",a)
return "hello"
return inner_func2
x=func()
print(x)
xx=x()
print(xx)
结果为:
190
--->inner_func2 100
hello
总结:
1、闭包优化了代码,原来类对象完成的工作,闭包也可以完成
2、由于闭包引用了外部函数的局部变量,则外部函数的局部变量没有及时释放,消耗内存
3、闭包的好处:使得代码简洁
4、闭包是理解装饰器的基础
3、闭包的例子:计数器
def generate_count():
container=[0]
def add_one():
container[0]=container[0]+1
print("当前是第{}次访问".format(container[0]))
return add_one
counter=generate_count()
counter()
counter()
counter()
结果为:
当前是第1次访问
当前是第2次访问
当前是第3次访问
3、装饰器
装饰器的应用场景:
比如判断用户的登录状态,登录了才能加入购物车,才能付款等
装饰器的特点:
1、函数A是作为参数出现(函数B就接收了函数A作为参数)
2、要有闭包的特点