1.函数在内存中的执行机制:
当定义函数def func(a,b):, 相当于定义了一个变量func,其指向在内存中开辟空间保存的形参a、b和定义函数时的逻辑程序,即定义函数,相当于定义了一个新变量。当调用函数时,例如a=func(5,10),相当于将 实参5,10传递给func,开始执行函数,之后将结果赋值给a。
另外python和C语言中定义函数不同。c语言中函数可以重名,只要参数类型不同即可。python中则不同,再定义函数func(a,b)时,相当于将func变量指向新的函数内存空间。没有实际意义。
2.函数中参数*args,**kwargs总结:
*args表示位置传参,**kwargs表示关键字传参。*的作用:解包,可以将可迭代对象中的数据一一列出。*args可解元组,列表;对字典的解包*kwargs是key,kwargs是原字典。
3.闭包函数:
闭包:封闭的包装,防止对象被外界影响。在python中,函数可以嵌套,内嵌的函数可以自由使用外部函数定义的局部变量。将内嵌函数进行打包的过程成为闭包。接下来分析一下闭包的过程。
问题:闭包时,到底有没有打包外部函数的局部变量和内嵌函数的形参?
如下例子:我们通过读取局部变量i和内嵌函数形参a的id值,来分析打包的过程
def func(i=[]):
def func1(a=[]):#line2
print(id(a))#line3
print(id(i))
a.append(5)
i.append(5)
print(a)
print(i)
print("----------")
return func1
b=func()#执行过程相当于执行line2,定义了一个新变量func1,并将line2下面的函数程序加载到内存中,并传递给变量func1
print(b())#执行func1指向的对象,即指向func1函数,直接执行line3
c=func()#执行line2,又定义了一个新变量func1,并指向line2下面的程序。
print(c())
调试结果:
10373720
10372560
[5]
[5]
----------
None
12569376
10372560
[5]
[5, 5]
----------
打印的结果有较大的差异。我们发现,闭包时自由变量i指向的地址是同一个。每次打包,数据结果相同。可以认为,自由变量i没有打包。
相反,对于闭包函数,每次调用func,其形参a在内存中都存储一次[]的引用地址,即每次打包时,执行一次a=[].形参a中存放的引用地址不同。
结论:闭包时,只打包内嵌函数及内嵌函数的形参 ,外部函数的自由变量并没有进行打包。原因:自由变量的所有权是属于外层函数的,其实外部函数定义时,已经在内存中开辟空间存储了自己的局部变量。