TUE.函数
什么是函数
- 盛放功能的容器,方便重复使用
使用原则
- 先定义后调用
类型提示
-
Type hinting
-
Python3(3.5 以上版本)新增类型提示功能,例如我们可以为函数增加类型提示信息,而不影响函数本身的执行
- 注释的一般规则是参数名后跟一个冒号’:’,然后再跟一个 expression,这个 expression 可以是任何形式
def func(a: 'spam', b:(1, 10), c: float) --> int: return a + b + c func(1, 2, 3) print(func.__annotations__) # 可以查看所有的提示信息
- Python 是一门解释型的强类型动态语言
-
调用函数的两种格式
-
语句式:单纯执行命令
-
表达式:加入运算符即表达式
函数返回值
-
return 是函数结束的标志,即函数体代码一旦运行到 return 会立刻终止函数运行,并且将 return 后的值当做本次运行的返回值
-
返回 None
def func(): pass # return # return None # PS: 以上三种形式返回值均为 None
-
返回一个值: return 值
def func(): return 10
-
返回多个值: 返回数据类型为元组
def func(): return 10, aa, [1, 2] # 只需要 ',' 隔开, 不需要加括号 res = func() print(res,type(res))
- 返回值是为了将经过一系列函数代码处理的结果反馈给函数的调用者,做进一步的处理
-
-
形参与实参
-
形参: 在定义函数阶段定义的参数称之为形式参数,简称形参,相当于变量名
def func(x, y): print(x, y)
-
实参: 在调用函数阶段传入的值称为实际参数,简称实参,相当于变量值.实参是传入的值,而且实参只要是值就可以了,但值可以是以下形式
1. func(1, 2) 2. a = 1, b = 2 func(a, b) 3. func(int('1'), 2) func(func(1, 2) func(2, 3), 333)
-
形参与实参的关系
- 在调用阶段,实参 (变量值) 会绑定给形参 (变量名)
- 这种绑定关系只能在函数体内使用
- 实参与形参的绑定关系在函数调用时生效,函数调用结束后解除绑定关系
-
-
形参与实参的具体使用
-
位置参数: 按照从左到右的顺序依次定义的参数
- 位置形参: 在函数定义阶段,按照从左到右的顺序直接定义的"变量名" ,此参数必须被传值, 且个数必须相等
def func(x, y):
- 位置实参: 在函数调用阶段,按照从左到右的顺序依次传入的值,且按照顺序与形参一一对应
def func(x, y): pass func(1, 2)
-
关键字参数
- 关键字实参: 在函数调用阶段, 按照 key = value 的形式传入的值, 即指名道姓给某个形参传值,可以完全不参照顺序
def func(y=2, x=3)
-
混合参数
- 位置实参必须放在关键字实参前
func(1, y=2)
- 不能为同一个形参重复传值
func(1, y=2, x=3) TypeError: func() got an unexpected keyword argument 'x'
-
默认参数
- 默认形参:在定义函数阶段,就已经被赋值的形参,称之为默认参数
- 特点:在定义形参已经为其赋值,在调用阶段可以不传值
def func(x, y=3): print(x, y) func()
-
位置形参与默认形参混用,强调:
-
可变长度的参数(*与**的用法)
- 在形参中带*: *会将溢出的位置实参汇总成元组,然后赋值给紧跟其后的形参名
- 在形参中带’’: ''会将溢出的关键字实参汇总成字典,然后赋值给紧跟其后的形参名
-
特点
- 可变长度指的是在调用函数时,传入的值(实参)的个数不固定
- 实参是用来为形参赋值的,因此针对溢出的实参必须有对应的形参来接收
I: 1. 可变长度的位置参数 """ * + 形参名(*args):用来接收溢出的位置实参,溢出的位置实参会被'*'保存成元组的格式然后赋值给变量名 *后跟的可以使任意名字,但是约定俗成的规范是 *args """ def func(x, y, *z): # z = (3, 4. 5. 6) print(x, y, z) func(1, 2, 3, 4, 5, 6) 2. 可变长度的关键字参数 """ ** + 形参名(**kwargs): 用来接收溢出的关键字实参,溢出的关键字实参会被'**'保存成字典格式,然后赋值给变量名 **后跟的可以使任意名字,但约定俗称的规范是 **kwargs """ def register(name, age, **kwargs) print(name, age) register('egon', 18, 'male') # 强调: 定义阶段的'*'与'**'只用于打包汇总,不负责解包,若传入的 可变长度的关键字参数 为字典,必须先用'**'解包,否则会因为缺少 value 值无法打包而报错
II: *可以用在实参中,实参中带*,*后的实参打散成位置实参,然后再与形参一一对应 l = [1, 2, 3] def func(x, y, z) print(x, y, z) func(*l) func(*'hello') # 'h', 'e', ('l', 'l', 'o') **可以用在实参中,但**后必须跟字典,并打散为关键字实参,再与形参一一对应 def func(x, y, **kwargs): print(x, y, **kwargs) func(**{'x': 1, 'y': 2,'a': 3,'b': 4}) # 1 2 {'a': 3,'b': 4}
III: 形参与实参中都带*,*args 必须在 **kwargs 之前 def func(*args, **kwargs): print(*args) print(*kwargs) # 只要传参时符合参数规范(位置参数在关键字参数之前),可以传无限多个值
带’*'的实参相当于对实参进行 for 循环
-
-
命名关键字参数(了解)
-
在定义函数时, *后定义的参数,如下所示,称之为命名关键字参数
- 命名关键字实参只能按照 key = value 的关键字实参 形式为其传值
def func(x, y, *, a, b): print(x, y) print(a, b)
-
-
组合使用(了解)
-
完整函数形式 – def foo(x, y, *args, m = 666, n, **kwargs)