本篇文章主要是对python学习时的一些总结,作为学习笔记记录。
之前介绍了关于函数的基本结构,参数传递时的装包和解包,这篇文章主要说明函数嵌套调用,内部函数,闭包和装饰器的概念。
函数嵌套调用
函数嵌套调用是指在函数内部又调用了别的函数。
def func1():
print(1)
def func2():
func1()
print(2)
func2()
结果为:
1
2
内部函数
函数嵌套调用只是在函数内部调用另外的函数,而内部函数则是在函数内部嵌套定义函数。
之前我们提到过函数静态变量的概念,那时我们猜测python中的函数可能是一个特殊的类型,可以在函数内部声明属于函数的成员变量。而内部函数可以认为是在函数这个特殊类型内部又声明了一个特殊类型的变量。
当然,内部函数也具有一些特点:
- 内部函数可以访问外部函数的变量
- 内部函数可以修改外部函数可变类型的变量
- 内部函数修改全局的不可变类型变量时,需要在内部函数对应变量前用global关键字修饰
- 内部函数修改外部函数的不可变类型变量时,需要在内部函数对应变量前用nonlocal关键字修饰
- locals()可以查看本地变量,结果以字典形式输出
- globals()可以查看全局变量,结果以字典形式输出
name = 'wood'
grade = [70,80,90]
def func():
# 外部函数声明
admin = 'jack'
time = [20,30,40]
# 函数定义
def foo():
global name
nonlocal admin
inner = 'foo'
print(name, grade, admin, time, inner)
name = 'tom'
grade[1] = 100
admin = 'anna'
time[1] = 50
print(name, grade, admin, time, inner)
print(locals())
print(globals())
# 函数调用
foo()
func()
结果为:
wood [70, 80, 90] jack [20, 30, 40] foo
tom [70, 100, 90] anna [20, 50, 40] foo
{'inner': 'foo', 'time': [20, 50, 40], 'admin': 'anna'}
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000001DDA7B3E208>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'F:/....../demo.py', '__cached__': None, 'name': 'tom', 'grade': [70, 100, 90], 'func': <function func at 0x000001DDA7C0DBF8>}
从上边的结果可以看出:
- 在内部函数中,可以直接修改外部函数的可变类型变量,但是只能修改,不能重新赋值,否则会被认为是内部函数的局部变量
- 在内部函数中调用locals(),包含的也有外部函数的局部变量
闭包
在外部函数中定义内部函数,并且内部函数中使用到了外部函数的变量,并且在外部函数中返回内部函数,python中把这种情况叫做闭包。闭包是装饰器的基础,而内部函数则是闭包的基础。
从上边闭包的定义看来,闭包的形成需要有几个条件:
- 外部函数中定义了内部函数
- 内部函数引用了外部函数的变量
- 外部函数是有返回值
- 返回的值是:内部函数名
def func():
a = 10
def foo():
b = 20
print(a, b)
return foo
handle = func()
handle()
结果为:
10 20
从上边的结果可以看出:
- 闭包可以借由外部函数返回内部函数的句柄,从而在函数外部实现内部函数的调用
- 闭包可以使用同级的变量
- 闭包能够读取其它元素的内部变量
- 闭包能够延长变量的作用域
但闭包也会存在一定的缺点:
- 闭包中变量的作用域没有那么直观
- 闭包中变量不会被垃圾回收,因此会有一定的内存占用问题
对于闭包来说:
- 闭包优化了变量,原来需要类对象完成的工作,闭包也可以完成
- 由于闭包引用了外部函数的局部变量,外部函数的局部变量没有得到及时释放,会消耗内存
- 闭包能够让代码变得简介,便于用户阅读
- 内部函数是闭包的基础,闭包是装饰器的基础