参数匹配模型——Python学习之参数(二)

参数匹配模型——Python学习之参数(二)

位置参数:从左至右进行匹配

一般情况下,也是我们最常使用的那种方法,通过位置进行匹配,把参数值传递给参数头部的参数名称,匹配顺序从左到右。

例如:

def func(name, father_name):
    print("%s's father is %s"%(name, father_name))

func('Xiaowang', 'Laowang')
func('Laowang', 'Xiaowang')

运行结果是:

Xiaowang's father is Laowang
Laowang's father is Xiaowang

关键字参数:通过参数名进行匹配

调用者可以定义哪一个参数接受这个值,通过在调用时使用参数的变量名,即 name=value这种语法。

例如:

def func(name, father_name):
    print("%s's father is %s"%(name, father_name))

func(name='Xiaowang', father_name='Laowang')
func(father_name='Laowang', name='Xiaowang')

运行结果是:

Xiaowang's father is Laowang
Xiaowang's father is Laowang

默认参数:为没有传入值的参数定义参数值

如果调用时传入的值过于少的话,函数能够为参数指定默认值,这里再次使用语法 name=value.

例如:

def func(name, age=10):
    print("%s's age is %d"%(name, age))

func('Wang', 20)
func('Wang')  # age使用默认值10

运行结果是:

Wang's age is 20
Wang's age is 10

可变参数:收集任意多于基于位置或关键字的参数

如果参数名称以字符*开头,则表示收集任意多的额外参数(这个特性常常叫做可变参数)。

例如:

def print_params(*params):  
	print(params) 

这里好像只指定了一个参数,但它前面有一个星号。这是什么意思呢?尝试使用一个参数来调用这个函数,看看结果如何。

>>> print_params('Testing') 
>>> ('Testing',) 

注意到打印的是一个元组,因为里面有一个逗号。也就是说前面有星号的参数将被放在元组中?咱们再试试。

>>> print_params(1, 2, 3) 
(1, 2, 3) 

可见,参数前面的星号将提供的所有值都放在一个元组中,也就是将这些值收集起来。

再看一个例子:

def print_params_2(title, *params):  
    print(title) 
    print(params) 

>>> print_params_2('Params:', 1, 2, 3) 
Params: 
(1, 2, 3) 

因此星号意味着收集余下的位置参数。如果没有可供收集的参数,params将是一个空元组。

>>> print_params_2('Nothing:') 
Nothing: 
() 

带星号的参数也可放在其他位置(而不是最后),但不同的是,在这种情况下你需要做些额外的工作:使用名称来指定后续参数。

>>> def in_the_middle(x, *y, z): 
...     print(x, y, z) 
... 
>>> in_the_middle(1, 2, 3, 4, 5, z=7) 
1 (2, 3, 4, 5) 7 
>>> in_the_middle(1, 2, 3, 4, 5, 7) 
Traceback (most recent call last):  
  File "<stdin>", line 1, in <module> 
TypeError: in_the_middle() missing 1 required keyword-only argument: 'z' 

第9行的keyword-only argument后文会讲。

星号不会收集关键字参数。

def print_params_2(title, *params):  
    print(title) 
    print(params) 

>>> print_params_2('Hmm...', something=42) 
>>> Traceback (most recent call last):  
>>>   File "<stdin>", line 1, in <module> 
>>> TypeError: print_params_2() got an unexpected keyword argument 'something' 

要收集关键字参数,可使用两个星号。

>>> def print_params_3(**params): 
...     print(params) 
... 
>>> print_params_3(x=1, y=2, z=3) 
{'z': 3, 'x': 1, 'y': 2} 

如你所见,这样得到的是一个字典而不是元组。

可变参数解包:传递任意多的基于位置或关键字的参数

调用者能够再使用*语法将参数集合打散,分成参数。这个*与在函数头部的*恰恰相反:在函数头部它意味着收集任意多的参数,而在调用者中意味着参数解包。

例如,我们能够通过一个元组给一个函数传递4个参数。

>>> def func(a, b, c, d):
...     print(a, b, c, d)
... 
>>> args = (1, 2, 3, 4)
>>> func(*args)
1 2 3 4

类似地,如果在调用函数时,**会以键值对的形式解包一个字典,使其成为关键字参数。

>>> def func(a, b, c, d):
...     print(a, b, c, d)
... 
>>> args = {'a':2, 'b':4, 'c':6, 'd':8}
>>> func(**args)
2 4 6 8

提示

不要混淆函数头部或函数调用时*或者**的语法:在函数头部它意味着收集任意数量的参数,在函数调用时,它解包任意数量的参数。

Keyword-only参数:参数必须按照名称传递

Python3.0 把函数头部的排序规则通用化了,允许我们指定 keyword-only 参数,即必须只按照关键字传递并且不会由一个位置参数来填充的参数。

从语法上讲, keyword-only 参数编码为命名的参数,出现在参数列表中的 *args 之后,所有这些参数都必须在调用中使用关键字语法来传递。例如,在下面的代码中, 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() missing 1 required keyword-only argument: 'c'

我们也可以在参数列表中使用一个*字符,来表示一个函数期待跟在*后面的所有参数都作为关键字参数传递。在下面的例子中,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 1 positional argument but 3 were given
>>> kwonly(1)
TypeError: kwonly() missing 2 required keyword-only arguments: 'b' and 'c'

仍然可以对 keyword-only 参数使用默认值,即便它们出现在函数头部中的*后面。在下面的例子中,a 可能按照名称或位置传递,而 b 和 c 是可选的,但是如果使用的话必须按照关键字传递。

>>> def kwonly(a, *, b='spam', c='ham'):
        print(a, b, c)
>>> kwonly(1)
1 spam ham
>>> kwonly(1, c=3)
1 spam 3
>>> kwonly(a=1)
1 spam ham
>>> kwonly(c=3, b=2, a=1)
1 2 3
>>> kwonly(1, 2)
TypeError: kwonly() takes 1 positional argument but 2 were given

实际上,带有默认值的 keyword-only 参数是可选的,但是,那些没有默认值的 keyword-only 参数真正地变成了函数必须的 keyword-only 参数。咱们再看几个例子:

>>> def kwonly(a, *, b, c='spam'):
        print(a, b, c)
>>> kwonly(1, b='eggs')
1 eggs spam
>>> kwonly(1, c='eggs')
TypeError: kwonly() missing 1 required keyword-only argument: 'b'
>>> kwonly(1, 2)
TypeError: kwonly() takes 1 positional argument but 2 were given
>>> def kwonly(a, *, b=1, c, d=2):
        print(a, b, c, d)
>>> kwonly(3, c=4)
3 1 4 2
>>> kwonly(3, c=4, b=5)
3 5 4 2
>>> kwonly(3)
TypeError: kwonly() missing 1 required keyword-only argument: 'c'
>>> kwonly(1, 2, 3)
TypeError: kwonly() takes 1 positional argument but 3 were given

相关文章:Python学习之参数(一)

参考资料

《Learning Python,5th Edition》

《Python基础教程》人民邮电出版社,第3版

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值