Python - 参数匹配模型

以下内容参考自《Python学习手册》

 

1. 匹配语法表

语法位置解释
func(value)调用者常规参数:通过位置进行匹配
func(name=value)调用者关键字参数:通过变量名匹配
func(*tuple)调用者以name(一个元组)传递所有的对象,并作为独立的基于位置的参数(解包参数)
func(**dict)调用者以name(一个字典)传递所有的键值对,并作为独立的关键字参数(解包参数)
def func(name)函数常规参数:通过位置或变量名进行匹配
def func(name=value)函数默认参数值,如果没有在调用中传递的话
def func(*name)函数匹配并收集(在元组中)所有包含位置的参数
def func(**name)函数匹配并收集(在字典中)所有包含位置的参数
def func(*args, name)函数参数必须在调用中按照关键字传递
def func(*, name=value) (Python3)

 

2. 顺序法则

  • 在函数调用中,参数必须以此顺序出现:任何位置参数(value),后面跟着任何关键字参数(name=value)和*tuple形式的组合,后面跟着**dict形式。
  • 在函数头部,参数必须以此顺序出现:任何一般参数(name),紧跟着任何默认参数(name=value),如果有的话,后面是*name的形式,最后是**name形式。

 

3. 参数匹配顺序

  • 通过位置分配非关键字参数;
  • 通过匹配变量名分配关键字参数;
  • 其他额外的非关键字参数分配到*name元组中;
  • 其他额外的关键字参数分配到**name字典中;
  • 用默认值分配给在头部未得到分配的参数。

e.g.

>>> def func(a, b=2, *args, **kwargs):
...     print a
...     print b
...     print args
...     print kwargs
...
>>> func(1, 2, 3, 4, c=5, d=6)
1
2
(3, 4)
{'c': 5, 'd': 6}
>>> func(1, 2, *(3, 4), **dict(c=5, d=6))
1
2
(3, 4)
{'c': 5, 'd': 6}
>>> func(1, *(3, 4), **dict(c=5, d=6))
1
(4,)
{'c': 5, 'd': 6}
>>> func(1, 2, b=2)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: func() got multiple values for keyword argument 'b'
>>> func(1, 2, c=3, d=4, 5, 6)
  File "<stdin>", line 1
SyntaxError: non-keyword arg after keyword arg
>>> func(1, 2, c=3, *(5, 6), **dict(d=4))
  File "<stdin>", line 1
SyntaxError: non-keyword arg after keyword arg
>>> func(1, 2, *(5, 6), c=3, **dict(d=4))
  File "<stdin>", line 1
SyntaxError: non-keyword arg after keyword arg
>>> func(1, 2, c=5, *(3, 4), **dict(d=6))
1
2
(3, 4)
{'c': 5, 'd': 6}
>>> func(1, 2, *(3, 4), c=5, **dict(d=6))
1
2
(3, 4)
{'c': 5, 'd': 6}
>>> func(1, 2, **dict(c=5, d=6), *(3, 4))
  File "<stdin>", line 1
    func(1, 2, **dict(c=5, d=6), *(3, 4))
                               ^
SyntaxError: invalid syntax

 

4. Python3.0 Keyword-Only参数

keyword-only参数编码为命名的参数,出现在参数列表中的*args之后。所有这些参数都必须在调用中使用关键字语法来传递。

e.g. 在如下的代码中,a可能按照名称或位置传递,b收集任何额外的位置参数,并且c必须只按照关键字传递:

>>> def kwonly(a, *b, c):
...    print(a, b, c)
...
>>> kwonly(1, 2, c=3)
1 (2,) 3
>>> kwonly(a=1, c=3)
1 () 3
>>> kwonly(1, 2, 3)
TypeError: kwonly() needs keyword-only argument c

我们也可以在参数列表中使用一个*字符,表示一个函数不会接受一个可变参数列表,而且*后面的所有参数都作为关键字传递。

e.g. 在以下函数中,a可以按照位置或名称传递,但b和c必须按照关键字传递,不允许其他额外的位置传递:

>>> def kwonly(a, *, b, c):
...    print(a, b, c)
...
>>> kwonly(1, c=3, b=2)
1 2 3
>>> kwonly(c=3, b=2, a=1)
1 2 3
>>> kwonly(1, 2, 3)
TypeError: kwonly() takes exactly 1 positional argument (3 given)
>>> kwonly(1)
TypeError: kwonly() needs keyword-only argument b

 

5. 默认参数陷阱

Python会将默认参数保存为对象附加在函数本身。如果默认参数为可变对象的话,该函数的多次调用就必须格外小心,因为一次修改可能会对下一次的调用造成影响。e.g.

>>> def func(x=[]):
...     x.append(1)
...     print x
...
>>> func()
[1]
>>> func()
[1, 1]
>>> func()
[1, 1, 1]

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值