3
函数语法
def function_name(parameterlist):
['''comments''']
[functionbody]
function_name:函数名称
parameterlist:可选参数,用于指定向函数中传递的参数
comments:可选,表示为函数指定注释,如果指定了该参数,在调用函数时,输入函数名称和左侧小括号,会显示这段信息
functionbody:函数体
函数声明
def创建了一个对象并将其赋值给某个变量名
当python运行到def语句时,将生成一个新的函数对象并将其赋值给这个函数名
函数名,是对函数对象的引用
函数名(),是对函数对象的调用,即执行
函数参数
- 形参:形式参数,在定义函数时,函数名后面的括号中的参数是形参
- 实参:实际参数,在调用函数时,函数名后面的括号中的参数是实参
参数传递
本质上是形参和实参对同一个对象的共享引用,表现为:
- 不可变对象因为不可改变,可以看做传入了"值"
- 可变对象因为可以改变,可以看做传入了"指针"
不可变对象:数字、字符串、元组
可变对象:列表、字典
其实都是传入了指针,重新赋值导致形参变量指向了新的对象,即新的引用,和实参变量不再共享引用;原位置改变并没有导致形参变量产生新的引用,仍然是共享引用。
形参在函数体中是局部变量,不可以被声明为全局变量
对形参的重新赋值,不会影响实参
对形参的原位置修改会影响实参
参数匹配顺序
1、位置顺序
2、关键字参数
3、默认参数
4、可变长参数
参数匹配与函数调用
定义:常规参数
调用:通过位置次序或关键字名称匹配
>>> def fun1(a,b,c):print(a,b,c)
基于位置调用
>>> fun1(1,2,3)
1 2 3
基于关键字调用,参数顺序不再重要,因为不基于位置
>>> fun1(b=2,c=3,a=1)
1 2 3
混合调用,先匹配基于位置的参数,再匹配基于关键字的参数,
>>> fun1(1,c=3,b=2)
1 2 3
解包调用1,列表
>>> L = [1,2,3]
>>> fun1(L) 直接传入L,会被认为只传入了一个参数
Traceback (most recent call last):
File "<pyshell#44>", line 1, in <module>
fun1(L)
TypeError: fun1() missing 2 required positional arguments: 'b' and 'c'
>>> fun1(*L) 解包L
1 2 3
解包调用2,字典
>>> L = [1,2,3]
>>> D = {'a':1,'b':2,'c':3}
>>> fun1(D)
Traceback (most recent call last):
File "<pyshell#47>", line 1, in <module>
fun1(D)
TypeError: fun1() missing 2 required positional arguments: 'b' and 'c'
>>> fun1(**D)
1 2 3
定义:默认值参数
调用:无论基于位置还是基于关键字调用,如果在调用时,没有传入参数,使用默认值
>>> def fun1(a,b=2,c):print(a,b,c)
SyntaxError: non-default argument follows default argument
>>> def fun1(a,b,c=4):print(a,b,c)
>>> fun1(1,2) 不传入c,则使用默认参数
1 2 4
>>> fun1(1,2,3)
1 2 3
定义:可变长参数
调用:可以传入任意个数的参数,
- *arge
函数将这些参数收集到一个元组中,可以被索引或for循环遍历
>>> def fun1(*args):print(type(args),args)
>>> fun1(1)
<class 'tuple'> (1,)
>>> fun1(1,2)
<class 'tuple'> (1, 2)
>>> fun1(1,2,3)
<class 'tuple'> (1, 2, 3)
- **arges
只对关键字参数有效,函数将这些参数收集到一个字典中
>>> def fun1(**args):print(type(args),args)
>>> fun1(a=1,b=2)
<class 'dict'> {'a': 1, 'b': 2}
>>> fun1(a=1)
<class 'dict'> {'a': 1}
函数体
流程控制语句
if语句
if con1:…
elif con2:…
else:…
for语句
for i in iterator:…
while语句
while con1:…
try语句
try:可能发生错误的代码
except [ExceptionName [as alias]]:发现对应异常时要执行的语句
else:没有发现异常时要执行的语句
finally:无论程序中是否有异常产生,都会执行的语句
break 结束整个循环
continue 结束本次循环
pass 占位符,什么也不做
exit() 退出整个程序
变量
- 全局变量
在函数体外定义(赋值)的变量,或者在函数内部通过global声明的变量是全局变量
在函数内部,
对全局变量的引用不需要声明,因为对变量名的查找遵循LEGB顺序
对全局变量的重新赋值需要global声明,如果不声明,就成了赋值定义了一个局部变量,按照LEGB的顺序,局部变量会覆盖全局变量或内置变量
- 局部变量
在函数中被定义(赋值)的变量是局部变量,仅在函数运行的过程中存在,在函数调用时生成,在函数退出时消失
作用域
python创建、改变或查找变量名都是在命名空间中进行的。作用域就是命名空间。
函数内变量名解析机制为LEGB,即查找顺序
- 局部作用域 (L)
- 外层函数作用域(E)
- 全局作用域(G)
- 内置作用域(B)
变量与作用域的对应
- 局部变量的作用域为局部作用域(包括内层函数)
在函数内定义(赋值)的变量名与在函数外定义的变量名并不冲突,即使是相同的变量名
局部变量a与全局变量a,互不冲突即两个变量为a与fun1.a,局部变量a只在函数体内有效
- 全局变量的作用域为全局作用局
- 在函数体内重新赋值全局变量,或在函数体内声明全局变量,使用global
在函数体内重新赋值全局变量
在函数体内声明全局变量
- 在函数体内原位置改变对象(注意,这不是重新赋值)不会把变量划分为局部变量,只有对变量赋值才会划分为局部变量
不可变对象:数字、字符串、元组
可变对象:列表、字典
函数返回值
函数通过return语句将计算得到的值(函数调用的结果)传回给调用者
yield向调用者返回一个结果,并记住离开的位置
没有返回语句的函数在执行结束时,返回None对象