Python 五类参数
- 默认参数
- 位置参数(positional argument)
- 关键字参数(keyword argument)
- 可变位置参数
- 可变关键字参数
默认参数很好理解,如果不传参给那个参数的话,就使用定义时候设置的默认值:
def f(a=0): print(f'a:{a}') #两种调用方式 f() f(1) output: 0 1
如果一个函数有一个参数a,根据调用函数f时的传参方式不同,a即可能是位置参数,也可能是关键字参数。
def f(a): print(f'a:{a}')
位置参数的调用
f(1) a:1
关键字参数的调用
f(a=1) a:1
如果有一个函数以如下方式定义:
def f(a, *b, **c): print(f'a:{a},b:{b},c:{c}')
函数 f 的参数稍显复杂,但也是最常用的函数参数定义结构。
- 出现带一个星号的参数 b,这是可变位置参数,被解析为元组;
- 带两个星号的参数 c,这是可变关键字参数,被解析为字典。
f(1,2,3,w=4,h=5) f(1,2,w=4) output: a:1,b:(2, 3),c:{'w': 4, 'h': 5} a:1,b:(2,),c:{'w': 4}
可变表示函数被赋值的变量个数是变化的。
查看参数
借助 Python 的 inspect 模块查看参数的类型:
from inspect import signature
def f(a,*b): print(f'a:{a},b:{b}') for name,val in signature(f).parameters.items(): print(name,val.kind) output: a POSITIONAL_OR_KEYWORD b VAR_POSITIONAL
参数 a 既可能是位置参数,也可能是关键字参数。参数 b 为可变位置参数。
from inspect import signature def f(*,a,**b): print(f'a:{a},b:{b}') for name,val in signature(f).parameters.items(): print(name,val.kind) output: a KEYWORD_ONLY b VAR_KEYWORD
a 只可能为 KEYWORD_ONLY 关键字参数。就是因为定义a之前定义了一个*号,划重点,*号后面的参数只可能是关键字参数,不可能是位置参数
传递规则
Python函数定义时有一定的约束规则。如果不了解这些规则,函数调用时,可能会出现各种各样的调用异常。
常见的异常有以下六类:
SyntaxError: positional argument follows keyword argument
,位置参数位于关键字参数后面TypeError: f() missing 1 required keyword-only argument: 'b'
,必须传递的关键字参数缺失SyntaxError: keyword argument repeated
,关键字参数重复TypeError: f() missing 1 required positional argument: 'b'
,必须传递的位置参数缺失TypeError: f() got an unexpected keyword argument 'a'
,没有这个关键字参数TypeError: f() takes 0 positional arguments but 1 was given
,不需要位置参数但却传递 1 个
为了避免这些错误,只要摸索正确的使用规则就好了。
规则 1:不带默认值的位置参数缺一不可
规则 2:关键字参数(通过键=值传参的)必须在位置参数右边
def f(a,b): pass f(a=1,20) output: File "<ipython-input-21-bdc62c937217>", line 4 f(a=1,20) ^ SyntaxError: positional argument follows keyword argument
规则 3:对同一个形参不能重复传值
def f(a,**b): passf(1,width=20.,width=30.) SyntaxError: keyword argument repeated
规则 4:默认参数的定义应该在位置形参右面,默认参数通常应该定义成不可变类型。
规则 5:可变位置参数不能传入关键字参数
def f(*a): print(a) f(1) f(1,2,3) f(1,'ss',[1,2,3],4) #可变位置参数不能传入关键字参数 f(a=1) output: (1,) (1, 2, 3) (1, 'ss', [1, 2, 3], 4) --------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-24-e485cc7c8886> in <module>() 5 f(1,'ss',[1,2,3],4) 6 #可变位置参数不能传入关键字参数 ----> 7 f(a=1) TypeError: f() got an unexpected keyword argument 'a'
规则 6:可变关键字参数不能传入位置参数
def f(**a): print(a) f(a=1) f(a=1,b=2,width=3,lst=['a',['ssd',2,'s']]) f(1) output: {'a': 1} {'a': 1, 'b': 2, 'width': 3, 'lst': ['a', ['ssd', 2, 's']]} --------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-27-11c232a4bc21> in <module>() 4 f(a=1) 5 f(a=1,b=2,width=3,lst=['a',['ssd',2,'s']]) ----> 6 f(1) TypeError: f() takes 0 positional arguments but 1 was given