一 函数
1 函数的文档字符串
函数内的第一条语句是字符串时,该字符串就是文档字符串,用于对函数进行说明
利用文档字符串可以自动生成在线文档或打印版文档,建议在工作中习惯加入文档字符串,否则时间一长,自己可能都不知道函数是干嘛,更不用说其他人了
如上,利用__doc__属性,可以输出函数的文档字符串
在help()函数输出的相关信息中,也可输出文档字符串
print(help(sum_num))
执行结果
2 函数返回值
函数中有定义return 就是retun 后面计算出来的值
若函数中未定义return,函数返回值就是None,相当于定义了 return None
所以,每一个函数都对应一个return,函数执行完return就执行结束了
3 函数对象
定义了一个函数,实际上是定义了一个对象即函数对象,然后把函数名和这个对象关联在一起,用这个函数名指代函数对象
也可用其他变量名来指代函数对象并执行函数,如下
二、 函数参数
1 函数中的位置参数与关键字参数
如上,x为位置参数,y为关键字参数,y也是默认值参数,执行函数未传y的值,y的值就是默认值
函数定义时,关键字参数必须在位置参数后面,如下面的写法是错误的
def sum_num(x, y = 1, z):
xxxxx
如上, 关键字参数y=1必须放在最后面才行
收集函数参数
定义函数时,利用*xxx 与 **xxx的形式可以收集执行函数时传进来的多个参数如下
如上,告诉我没有传z的值
换一种执行方法如下
也可以把*xx放在最后
如上,我们可以看到执行函数时,通过xxx传递进来的参数放在一个数组里面
函数定义时,xxx的形式不能收集关键字参数如下
要在执行函数时收集关键字参数,可在函数定义时使用**xxx的形式,如下
如上,**xxx的形式可收集执行函数时传递进来的多个关键字参数,收集到的关键字参数放在一个字典里面
注意,函数定义时,与位置参数和关键字参数的关系一样,**xxx必须放在*xxx的后面
分配参数
在执行函数时使用*xxx或者**xxx的形式
使用如上,不过在执行函数时使用**xxx来分配字典参数显得很多余,我们可以直接传递字段进去,通过字典的属性来取值
三 函数作用域
除全局,作用域外,每一个函数的执行都有一个该函数的内部作用域
在函数内给变量赋值时,该变量为函数内部作用域内的变量,变量值得变动的影响范围也仅仅在该内部范围,函数外是的地方是看不见该变量或该变量的变动的
函数内读取变量时,按照函数内部作用域--函数外部作用域--全局作用域--python内置变量名来查找变量
所以,内部作用域与外部作用域有同名变量时:
处于内部,读取的就是内部作用域中 变量的值
处于外部,读取的就是外部作用域变量的值
如
上面在函数外部访问变量a, 和函数内的定义没关系,只能在外部作用域找,但外部并未定义a
如
上面,函数fa()内部读取a,首先会找函数内部作用域找,找不到才会其他作用域找,所以输出的是内部作用域定义的1
函数外部读取a,同样的道理,他会从自己所处的作用域找,自己作用域中定义的值是10,同时自己的作用域对函数fa而言, 是函数的外部作用域,虽然函数内也定义了a的值,但不会对外部作用域产生影响。所以a的值就是10
如
上面,函数fa()内部读取a,首先会找函数内部作用域找,找不到才会去其他作用域找,函数内部作用域并未定义a的值,读取的是外部a的值10
如果处于内部作用域,想给外部作用域的变量赋值,就要用global或者nonlocal
给外部全局作用域的变量赋值是用gloabl
给外部更上层函数中的变量赋值用nonlocal
如
在函数内部声明 gloabl a ,就是说a是外部全局作用域中的a,解析来在函数内部说的a都是全局作用域中的a,所以再把全局作用域a的值改为20后,读取的全局a的是就是20
在外部作用域读取a的值,由于函数fa先执行,函数改变外部作用域中a的值,所以输出的值是20
如果在外部中,在fa()运行前读取a就是10
如
如上,函数fa里面定义了函数fb, 函数fa返回一个函数对象即fb,每个函数都有自己的作用域
首先执行的是fa(),执行fa()时,只是返回函数对象fb,里面的函数fb并未执行,如果写成fa()()那就不光执行了fa,里面函数fb也执行了
现在只是执行fa,所以在fa的作用域中查找a b的值,刚好在该作用域中定义了a b的值,所以,结果就是定义的值
f = fa() fa的返回值是函数fb所指向的函数对象,所以f也执向了这个函数对象,执行f()也就是执行了函数fb()
在fb作用域中,声明nonloacal a,说明在fb中,所说的a就是外面更上层函数fa中的a,它把fa中的值变更为30,输出的值自然就是30
最后在全局作用域中读取a,当然首先会在全局作用域中查找a,该作用域相对于两个函数来说是外部作用域,加上又没有声明global,所以函数内如何折腾,都不会对外部的全局作用域产生影响,最终a的值就是全局作用域中的a
如
这是自己以前常犯的错误,在以前看来
a=a+1,首先会读取a的值,因为函数内部未定义a,所以读取a的值就是外部作用域中的10,所以结果是11
但就像前面开始所说的,在函数内部给变量a赋值,变量a就会被当作函数内部作用域的变量,但在赋值之前,函数内部作用域中并没有定义a
所以,要么在赋值前,在函数内部定义或传入一个a,要么通过global的方式把a做为全部变量都进来,然后给作为全局变量的a赋值