当前位置:   article > 正文

python 位置参数,默认参数, 可变参数,仅限关键字参数,可变关键字参数的详解及区别

仅限关键字参数

前言

在开始讨论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'>

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

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的各种参数

1.位置参数 positional

位置参数是按位置顺序传参的。

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'>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

2. 默认参数,关键字参数 default, keyword

函数定义时,如果有参数,则所有的形参名都是一个关键字,如果想通过关键字的方式传参,可以使用 关键字=值得方式传参,默认参数是在函数定义时就给参数传入了一个默认的参数值,如果函数调用时没有给这个参数传值,就使用默认值, 如果显式的传参了,就使用新传入的值代替默认值。

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

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

3. 可变参数 var_positional

可变参数是一个形参可以接受多个实参,用 ∗ 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'>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

值得一提的是,函数调用时各种参数的传入是有接受顺序的,如下, 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'
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

4. 可变关键字参数 var_keyword

可变关键字参数 用 双星号+参数名表示, 如: ∗ ∗ 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'>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

5. 仅限关键字参数 keyword_only

仅限关键字参数就是只能传入关键字参数,不能通过其他方式传参。仅限关键字参数不可缺省(除非有默认值),且只能强制性通过关键字传参。
在 定义参数时,若想指定仅限关键字参数,要把它们放在有的可变参数后面。即可变参数后面的关键字参数都是仅限关键字参数, 若不想要可变参数,只要仅限关键字参数,可以省略可变参数名,只留一个单星号*表示不接受任何可变参数,它可以作为普通参数的结束标志, 如下例:

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

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58

想了解更多仅限关键字参数, 可阅读:python 仅限关键字参数 keyword-only Arguments

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/261364
推荐阅读
相关标签
  

闽ICP备14008679号