知行编程网知行编程网  2022-11-14 12:30 知行编程网 隐藏边栏  61 
文章评分 0 次,平均分 0.0
导语: 本文主要介绍了关于5分钟搞定Python中函数的参数的相关知识,包括函数是什么,以及MID函数这些编程知识,希望对大家有参考作用。

5分钟获取Python中函数的参数

功能的灵活性非常高。除了常规定义的位置参数外,还支持默认参数、关键字参数、可变参数……这样不仅可以处理各种复杂的情况,还可以简化调用者的代码。


位置参数

调用函数时,一般根据函数定义的参数位置传递参数。这样的参数称为位置参数。

考虑下面的例子,函数包含了两个参数 - name 和 msg:

>>> def greet(name, msg):
...     print('Hello, {}, {}!'.format(name, msg))
...>>>

调用它很容易:

>>> greet('Pony', 'nice to meet you')
Hello, Pony, nice to meet you!

这里会按顺序依次赋值。由于“Pony”是第一个值,所以会赋值给第一个参数名;同样,“很高兴见到你”将分配给第二个参数 msg。

传递两个值时,函数运行平稳。但是如果参数的数量不匹配会发生什么?

>>> greet('Pony')  # 少一个参数
...
TypeError: greet() missing 1 required positional argument: 'msg'

显然,口译员会发牢骚。但是对于 Python 来说,解决这个问题是小菜一碟,请继续阅读!


默认参数

定义函数时,可以使用赋值运算符(=)来指定参数的默认值:

>>> def greet(name, msg = 'nice to meet you'):
...     print('Hello, {}, {}!'.format(name, msg))
...
>>>

注意:如果参数没有默认值,调用函数时必须为其指定一个值;如果有默认值,则调用时该值是可选的,如果为其提供了值,则默认值将被覆盖。

由于 name 没有默认值,所以必须指定一个值,而 msg 有一个默认值,所以该值是可选的:

>>> greet('Pony')                   # 使用默认值
Hello, Pony, nice to meet you!
>>>
>>> greet('Pony', 'give me a hug')  # 覆盖默认值
Hello, Pony, give me a hug!

值得注意的是,函数中的所有参数都可以有默认值,但是一旦存在默认参数,它右边的所有参数也必须有默认值。

也就是说,非默认参数不能出现在默认参数之后。例如,类似以下的内容将引发错误:

>>> def greet(msg = 'nice to meet you', name):
...     print('Hello, {}, {}!'.format(name, msg))
...
  File "<stdin>", line 1
SyntaxError: non-default argument follows default argument


关键字参数

为方便起见,Python 还允许使用 key = value 形式的关键字参数调用函数:

>>> def greet(name, msg):
...     print('Hello, {}, {}!'.format(name, msg))
...>>>

当以这种方式调用函数时,所有传递的关键字参数必须匹配函数接受的参数之一,并且它们的顺序无关紧要:

>>> greet(name = 'Pony', msg = 'nice to meet you')  # 按循序传递
Hello, Pony, nice to meet you!
>>>
>>> greet(msg = 'nice to meet you', name = 'Pony')  # 顺序颠倒也可以
Hello, Pony, nice to meet you!

此外,它可以与位置参数混合,但关键字参数必须在位置参数之后:

>>> greet('Pony', msg = 'nice to meet you')  # 位置参数与关键字参数混合使用
Hello, Pony, nice to meet you!

所以,如果像下面这样调用,就会报错:

>>> greet(name = 'Pony', message = 'nice to meet you')  # message 不存在
...
TypeError: greet() got an unexpected keyword argument 'message'
>>>
>>> greet(msg = 'nice to meet you', 'Pony')  # 关键字参数不能在位置参数之前
...
SyntaxError: positional argument follows keyword argument


可变参数

可变参数也称为不定长参数。顾名思义,传入的参数数量是可变的,可以是任意数字(0、1、2...)。 ``

包裹位置传递

可以在参数名称前添加星号 (*)。在函数内部,所有传入的参数都会通过变量名进行收集,最后按位置组合成一个元组:

>>> def greet(*names):
...     print('Hello,', names)
...
>>>

尝试一下,传递不同个数的参数:

>>> greet()  # 没有参数,为空元组
Hello, ()
>>>
>>> greet('Pony')
Hello, ('Pony',)
>>>
>>> greet('Jack Ma', 'Pony')
Hello, ('Jack Ma', 'Pony')

通常,可变参数 (*) 出现在参数列表的最后,因为它们收集传递给函数的所有剩余输入参数:

>>> def greet(msg, *names):
...     print('Hello, {}, {}!'.format(names, msg))
...
>>>
>>> greet('nice to meet you', 'Jack Ma', 'Pony')
Hello, ('Jack Ma', 'Pony'), nice to meet you!

话虽如此,可变参数(*)之后可以出现其他参数,但是这些形参是“强制关键字”参数,也就是说只能作为关键字参数,不能作为位置参数:

>>> def greet(*names, msg):
...     print('Hello, {}, {}!'.format(names, msg))
...
>>>
>>> greet('Pony', msg = 'nice to meet you')  # 只能被用作关键字参数
Hello, ('Pony',), nice to meet you!
>>>
>>> greet(msg = 'nice to meet you', 'Pony')  # 不能被用作位置参数
...
SyntaxError: positional argument follows keyword argument


包裹关键字传递

还有一种机制是在参数名称前添加两个星号(**),当这种形式出现时,msgs 将收集所有关键字参数,最后将它们组合成一个字典:

>>> def greet(**msgs):
...     print('Hello,', msgs)
...>>>

和上面一样,尝试传递不同个数的参数:

>>> greet()  # 没有参数,为空字典
Hello, {}
>>>
>>> greet(name = 'Pony')
Hello, {'name': 'Pony'}
>>>
>>> greet(name = 'Pony', msg = 'nice to meet you')
Hello, {'name': 'Pony', 'msg': 'nice to meet you'}

此外,*names 可以与 **msgs 形式的参数组合,但 *names 必须出现在 **msgs 之前。

例如,像下面这样,就会报错:

>>> def greet(**msgs, *name):
...
SyntaxError: invalid syntax


解包裹参数

与 [变量参数] 一样,* 和 ** 也可以在函数调用中使用。只是在这种情况下,与函数定义中的语义相反,参数将被解包而不是被包裹:

>>> def greet(name, msg):
...     print('Hello, {}, {}!'.format(name, msg))
...
>>>

尝试一下,元组用 * 来传递位置参数:

>>> t = ('Pony', 'nice to meet you')
>>> greet(*t)
Hello, Pony, nice to meet you!

同样地,字典也可以用 ** 传递关键字参数:``

>>> d = {'name':'Pony', 'msg':'nice to meet you'}
>>> greet(**d)
Hello, Pony, nice to meet you!


位置参数、默认参数、可变参数混合使用

根据上面的介绍,不难发现,当这些参数组合使用时,应该遵循一个基本原则:位置参数->默认参数->包装位置->包装关键字(定义和调用都应该遵循这个命令)。

例如,定义一个函数,能够同时向多个人发送多条消息:

>>> def greet(sender, address = 'BeiJing', *receivers, **msgs):
...     print('Hello, I am {}, from {}.'.format(sender, address))
...     print('-' * 30)      # 华丽的分割线
...     for rec in receivers:
...         for key, val in msgs.items():
...             print('No {}: {}, {}!'.format(key, val, rec))
...         print('-' * 30)  # 华丽的分割线
...
>>>

为了展示更好的效果,我们在中间穿插了一些华丽的分割线:

>>> greet('Waleon', 'Xi\'an', 'Jack Ma', 'Pony', one = 'nice to meet you', two = 'give me a hug')
Hello, I am Waleon, from Xi'an.
------------------------------
No one: nice to meet you, Jack Ma!
No two: give me a hug, Jack Ma!
------------------------------
No one: nice to meet you, Pony!
No two: give me a hug, Pony!
------------------------------

本文为原创文章,版权归所有,欢迎分享本文,转载请保留出处!

知行编程网
知行编程网 关注:1    粉丝:1
这个人很懒,什么都没写
扫一扫二维码分享