赞
踩
在开始讨论python各种类型的参数前,先介绍一个新知识inspect模块, 这个模块可以很好的展示出一个函数的参数信息,如下例:
from inspect import signature def func(a,b,*var, c, d, e=3, **kw): pass sig = signature(func) sig <Signature (a, b, *var, c, d, e=3, **kw)> str(sig) '(a, b, *var, c, d, e=3, **kw)' for name, param in sig.parameters.items(): print('参数类型:%s, 参数名:%s, 参数默认值:%s' %(param.kind, name, param.default)) 参数类型:POSITIONAL_OR_KEYWORD, 参数名:a, 参数默认值:<class 'inspect._empty'> 参数类型:POSITIONAL_OR_KEYWORD, 参数名:b, 参数默认值:<class 'inspect._empty'> 参数类型:VAR_POSITIONAL, 参数名:var, 参数默认值:<class 'inspect._empty'> 参数类型:KEYWORD_ONLY, 参数名:c, 参数默认值:<class 'inspect._empty'> 参数类型:KEYWORD_ONLY, 参数名:d, 参数默认值:<class 'inspect._empty'> 参数类型:KEYWORD_ONLY, 参数名:e, 参数默认值:3 参数类型:VAR_KEYWORD, 参数名:kw, 参数默认值:<class 'inspect._empty'>
inspect.signature 函数返回一个 inspect.Signature 对象,它有一个 parameters 属性,这是一个有序映射,把参数名和 inspect.Parameter 对象对应起来。各个 Parameter 属性也有自己的属性,例如 name、default 和 kind。特殊的inspect._empty 值表示没有默认值,考虑到 None 是有效的默认值(也经常这么做),而且这么做是合理的。
kind 属性的值是 _ParameterKind 类中的 5 个值之一,列举如下
POSITIONAL_OR_KEYWORD : 可以通过定位参数和关键字参数传入的形参(多数 Python 函数的参数属于此类)
VAR_POSITIONAL : 定位参数元组
VAR_KEYWORD : 关键字参数字典
KEYWORD_ONLY : 仅限关键字参数(Python 3 新增)
下面我们正式开始介绍python的各种参数
位置参数是按位置顺序传参的。
def func(a,b,c): print(a,b,c) # 如果不指定关键字,形参a, b, c绑定的值, 完全取决于实参传入的顺序 func(1,2,3) 1 2 3 func(3,2,1) 3 2 1 sig = signature(func) for name, param in sig.parameters.items(): print('参数类型:%s, 参数名:%s, 参数默认值:%s' %(param.kind, name, param.default)) 参数类型:POSITIONAL_OR_KEYWORD, 参数名:a, 参数默认值:<class 'inspect._empty'> 参数类型:POSITIONAL_OR_KEYWORD, 参数名:b, 参数默认值:<class 'inspect._empty'> 参数类型:POSITIONAL_OR_KEYWORD, 参数名:c, 参数默认值:<class 'inspect._empty'>
函数定义时,如果有参数,则所有的形参名都是一个关键字,如果想通过关键字的方式传参,可以使用 关键字=值得方式传参,默认参数是在函数定义时就给参数传入了一个默认的参数值,如果函数调用时没有给这个参数传值,就使用默认值, 如果显式的传参了,就使用新传入的值代替默认值。
def func(a,b, c='xxx'): # c在函数定义时就传入了一个默认值,c就是默认参数 print('a=', a) print('b=', b) print('c=', c) func(1,2) # 调用func函数时,没有给c指定传入的值,c就使用默认参数值 a= 1 b= 2 c= xxx func(1,2, c='000') # c指定传入值得话,使用指定值 a= 1 b= 2 c= 000 func(c='000', a='111', b='222') # 使用关键字传参,就无需在意参数的位置顺序 a= 111 b= 222 c= 000 sig = signature(func) for name, param in sig.parameters.items(): print('参数类型:%s, 参数名:%s, 参数默认值:%s' %(param.kind, name, param.default)) 参数类型:POSITIONAL_OR_KEYWORD, 参数名:a, 参数默认值:<class 'inspect._empty'> 参数类型:POSITIONAL_OR_KEYWORD, 参数名:b, 参数默认值:<class 'inspect._empty'> 参数类型:POSITIONAL_OR_KEYWORD, 参数名:c, 参数默认值:xxx
可变参数是一个形参可以接受多个实参,用 ∗ v a r a r g s \color{red}{*varargs} ∗varargs 标志这是一个可变参数。可变参数的传入数是不决定的,通常由函数调用方决定。可变参数会将所有接受的值以元组的形式传入函数体内,如果可变参数没有接受到任何值,则传入一个空元组(,)。
def func(a,b,*var,): print('a=', a) print('b=', b) print('var=', var) func(1,2,3,4,5) # a,b填满后, 剩下的都传给可变参数 a= 1 b= 2 var= (3, 4, 5) func(1,2,) a= 1 b= 2 var= () # 可变参数没有收到任何值,就是个空元组 sig = signature(func) for name, param in sig.parameters.items(): print('参数类型:%s, 参数名:%s, 参数默认值:%s' %(param.kind, name, param.default)) 参数类型:POSITIONAL_OR_KEYWORD, 参数名:a, 参数默认值:<class 'inspect._empty'> 参数类型:POSITIONAL_OR_KEYWORD, 参数名:b, 参数默认值:<class 'inspect._empty'> 参数类型:VAR_POSITIONAL, 参数名:var, 参数默认值:<class 'inspect._empty'>
值得一提的是,函数调用时各种参数的传入是有接受顺序的,如下, 4,5,6这三个实参传入时,位置参数会被优先赋值, 4,5会分别传给a, b。 接下来(6,7)传给var, 之后又出现a=1 这种关键字传参,因为a已经被赋过值了, 所以报错。关于函数传入顺序的具体描述, 可以点击查看这篇文章:参数调用行为,这里不在详解。
func(4,5,6,7 a=1,b=2)
Traceback (most recent call last):
File "/usr/lib/python3.6/code.py", line 91, in runcode
exec(code, self.locals)
File "<input>", line 1, in <module>
TypeError: func() got multiple values for argument 'a'
可变关键字参数 用 双星号+参数名表示, 如: ∗ ∗ k w a r g s \color{red}{**kwargs} ∗∗kwargs,可变关键字参数接收零个或多个关键字参数,并以字典的形式传入函数体,关键字为此字典的key,关键字绑定的值为value。如果可变关键字没有接收到任何参数, 则传入函数体一个空字典{}。
def func(a,b,*var, **kw): print('a=', a) print('b=', b) print('var=', var) print('kw=', kw) func(1,2,3,4, x1=11,x2=22,x3=33) # 传入多个关键字参数 a= 1 b= 2 var= (3, 4) kw= {'x1': 11, 'x2': 22, 'x3': 33} func(1,2,3,4, **{'y1':11, 'y2':22}) 使用 ** 解包字典 a= 1 b= 2 var= (3, 4) kw= {'y1': 11, 'y2': 22} func(1,2, **{'y1':11, 'y2':22}) a= 1 b= 2 var= () kw= {'y1': 11, 'y2': 22} func(1,2,) # 可变关键字参数,没有接收到任何值,就返回一个空字典 a= 1 b= 2 var= () kw= {} for name, param in sig.parameters.items(): print('参数类型:%s, 参数名:%s, 参数默认值:%s' %(param.kind, name, param.default)) 参数类型:POSITIONAL_OR_KEYWORD, 参数名:a, 参数默认值:<class 'inspect._empty'> 参数类型:POSITIONAL_OR_KEYWORD, 参数名:b, 参数默认值:<class 'inspect._empty'> 参数类型:VAR_POSITIONAL, 参数名:var, 参数默认值:<class 'inspect._empty'> 参数类型:VAR_KEYWORD, 参数名:kw, 参数默认值:<class 'inspect._empty'>
仅限关键字参数就是只能传入关键字参数,不能通过其他方式传参。仅限关键字参数不可缺省(除非有默认值),且只能强制性通过关键字传参。
在 定义参数时,若想指定仅限关键字参数,要把它们放在有的可变参数后面。即可变参数后面的关键字参数都是仅限关键字参数, 若不想要可变参数,只要仅限关键字参数,可以省略可变参数名,只留一个, 单星号*表示不接受任何可变参数,它可以作为普通参数的结束标志, 如下例:
def func(a,b, *args, e, f, g='xxx', **kw): print('a=', a) print('b=', b) print('args=', args) print('e=', e) print('f=', f) print('g=', g) print('**kw', kw) sig = signature(func) for name, param in sig.parameters.items(): print('参数类型:%s, 参数名:%s, 参数默认值:%s' %(param.kind, name, param.default)) 参数类型:POSITIONAL_OR_KEYWORD, 参数名:a, 参数默认值:<class 'inspect._empty'> 参数类型:POSITIONAL_OR_KEYWORD, 参数名:b, 参数默认值:<class 'inspect._empty'> 参数类型:VAR_POSITIONAL, 参数名:args, 参数默认值:<class 'inspect._empty'> 参数类型:KEYWORD_ONLY, 参数名:e, 参数默认值:<class 'inspect._empty'> 参数类型:KEYWORD_ONLY, 参数名:f, 参数默认值:<class 'inspect._empty'> 参数类型:KEYWORD_ONLY, 参数名:g, 参数默认值:xxx 参数类型:VAR_KEYWORD, 参数名:kw, 参数默认值:<class 'inspect._empty'> func(1,2,3,4, e='a',f='b',g='c', m='123', n='456') a= 1 b= 2 args= (3, 4) e= a f= b g= c **kw {'m': '123', 'n': '456'} def func(*, a, b): print(a, b) sig = signature(func) for name, param in sig.parameters.items(): print('参数类型:%s, 参数名:%s, 参数默认值:%s' %(param.kind, name, param.default)) 参数类型:KEYWORD_ONLY, 参数名:a, 参数默认值:<class 'inspect._empty'> 参数类型:KEYWORD_ONLY, 参数名:b, 参数默认值:<class 'inspect._empty'> func(a=1,b=2) # 必须强制通过关键字传参 1 2 func(1,2) # * 表示普通参数结束位, 再传入位置参数会报错 Traceback (most recent call last): File "/usr/lib/python3.6/code.py", line 91, in runcode exec(code, self.locals) File "<input>", line 1, in <module> TypeError: func() takes 0 positional arguments but 2 were given func(1,2,a=3,b=4) Traceback (most recent call last): File "/usr/lib/python3.6/code.py", line 91, in runcode exec(code, self.locals) File "<input>", line 1, in <module> TypeError: func() takes 0 positional arguments but 2 positional arguments (and 2 keyword-only arguments) were given
想了解更多仅限关键字参数, 可阅读:python 仅限关键字参数 keyword-only Arguments
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。