一、默认参数的陷阱
如果在行参中设置一个默认参数为一个空列表那么多次执行函数往里传值,下面的函数会共用这个列表。
def func(k,l = {}): l[k] = 'v' print(l) func(1) func(2) func(3)
结果:
{1: 'v'}
{1: 'v', 2: 'v'}
{1: 'v', 2: 'v', 3: 'v'}
二、三元运算(三目运算)
三个条件:
必须要有结果。
必须要有if和else
只可能是简单的情况
x = 4 y =2 a = x if x > y else y print(a)
三、 三种命名空间
内置命名空间 -- python解释器
就是python解释器一启动就可以使用,名字存储在内置命名空间中。
内置的名字在启动解释器的时候被加载进内存里。
全局命名空间 -- 写的函数,但不是函数中的代码
在程序从上到下被执行的过程中依次加载进内存的,放置了我们设置的所有变量名和函数名。
局部命名空间 -- 函数
函数内部定义的名字,当调用函数的时候才会产生这个命名空间,随着函数执行的结束,这个命名空间就消失了。
在局部:可以使用全局、内置命名空间中的名字
在全局:可以使用内置命名空间中的名字,但是不能用局部中使用
在内置:不能使用局部和全局的名字
a = 1 def func(): a = 2 def inner(): a = 3 def inner2(): print(a) inner2() inner() func()
在正常情况下,直接使用内置的名字。
当我们在全局定义了和内置名称空间中同名的名字时,会使用全局的名字。
当这个函数自己有的时候,就不找上级要了。
如果自己没有就找上一级要,上一级没有再找上一级,如果内置的名称空间都没有就报错。
def input(): print('in input now') def func(): print(input) func()
func ---> 函数的内存地址
函数名() 函数的调用
函数的内存地址() 函数的调用
五、作用域两种
全局作用域 --- 作用在全局 --- 内置和全局名字空间中的名字都属于全局作用域 globals()
局部作用域 --- 作用在局部 --- 函数(局部名字空间中的名字属于局部作用域) locals()
a = 1 def func(): global a a = 2 func() print(a)
在函数里默认只能读取全局作用域中的变量,如果想要修改全局作用域中的变量需要在函数的一开始添加global声明变量。
如果在一个局部(函数)内声明了一个global变量,那么这个变量在局部的所有操作将对全局的变量有效。
a = 1 b = 2 def func(): x = 'aaa' y = 'bbb' print(locals()) print(globals()) func() print(globals()) print(locals())
globals 不管在不在函数里都只打印全局的名字。
locals 输出什么根据locals所在的位置决定,如果在函数里输出函数,在全局则输出全局。
六、函数的嵌套
内部函数可以使用外部函数的变量
a = 1 def outer(): a = 1 def inner(): a = 2 def inner2(): nonlocal a #声明了一个上面第一层局部变量 a += 1 #不可变数据类型的修改 inner2() print('##a## : ', a) inner() print('**a** : ',a) outer() print('全局 :',a)
nonlocal 只能用于局部变量 找上层中离当前函数最近一层的局部变量
声明了nonlocal的内部函数的变量修改会影响到 离当前函数最近一层的局部变量
对全局无效,对局部 也只是对最近的一层有影响。
七、函数其他内容
1.函数名就是内存地址
2.函数名可以赋值
3.函数名可以作为容器类型的元素
4.函数名可以作为函数的返回值
5.函数名可以作为函数的参数
八、闭包
闭包就是嵌套函数,内部函数调用外部函数的变量
def outer(): a = 1 def inner(): print(a)
print(func1.__closure__)
return inner
inn = outer()
inn()
如果写嵌套函数想要调用函数里的函数就比较麻烦,所以用闭包就解决,直接调用inn就可以。
如果有多个inn a=1 则不会在内存中消失,会一直有直到inn函数停止才会消失。
检测 这个函数是不是闭包(__closure__)