Python函数参数

Python函数参数有三种格式,并且可以组合使用。

默认参数值

最常用的格式是给一个或多个参数名称添加默认值。如下所示:

def ask_ok(prompt, retries=4, reminder='Please try again!'):
    while True:
        ok = input(prompt)
        if ok in ('y', 'ye', 'yes'):
            return True
        if ok in ('n', 'no', 'nop', 'nope'):
            return False
        retries = retries - 1
        if retries < 0:
            raise ValueError('invalid user response')
        print(reminder)

该函数可以通过以下方式调用:

  • 提供唯一的强制参数prompt:ask_ok('Do you really want to quit?')
  • 提供可选参数:ask_ok('OK to overwrite the file?', 2)
  • 提供所有可选参数:ask_ok('OK to overwrite the file?', 2, 'Come on, only yes or no!')

该函数可以通过关键字参数的方式调用,若为关键字参数,则参数顺序可以任意,唯一的原则是,关键字参数只能在默认参数的后面。如下:

  • ask_ok(prompt="OK to overwrite the file?", retries=2, reminder='Come on, only yes or no!') (valid)
  • ask_ok(retries=2, reminder='Come on, only yes or no!', prompt="OK to overwrite the file?") (valid)
  • ask_ok(prompt="OK to overwrite the file?", 4, reminder='Please try again!') (invalid)

也即:位置参数不能在关键字参数之后

关键字参数

关键字参数的格式为kwarg=value,如下示例:

def parrot(voltage, state='a stiff', action='voom', type='Norwegian Blue'):
    print("-- This parrot wouldn't", action, end=' ')
    print("if you put", voltage, "volts through it.")
    print("-- Lovely plumage, the", type)
    print("-- It's", state, "!")

该函数可以接受一个必须参数(voltage)和三个可选参数(state,action, type已有默认值,可以不提供),可以通过以下方式调用:

parrot(1000)                                          # 1 positional argument
parrot(voltage=1000)                                  # 1 keyword argument
parrot(voltage=1000000, action='VOOOOOM')             # 2 keyword arguments
parrot(action='VOOOOOM', voltage=1000000)             # 2 keyword arguments
parrot('a million', 'bereft of life', 'jump')         # 3 positional arguments
parrot('a thousand', state='pushing up the daisies')  # 1 positional, 1 keyword

下面的调用全都非法:

parrot()                     # required argument missing
parrot(voltage=5.0, 'dead')  # non-keyword argument after a keyword argument
parrot(110, voltage=220)     # duplicate value for the same argument
parrot(actor='John Cleese')  # unknown keyword argument

在函数调用中,关键字参数必须位于位置参数之后。 传递的所有关键字参数必须与函数接受的参数之一匹配(例如actor对于parrot函数不是有效的参数),而且关键字参数的顺序并不重要。 这也包括非可选参数(例如parrot(voltage = 1000)也有效)。 任何参数都不能多次收到一个值。 由于此限制,以下示例失败了:

>>> def function(a):
...     pass
...
>>> function(0, a=0)
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
TypeError: function() got multiple values for keyword argument 'a'

特别的,当存在形式为**name的最终形式参数时,它会收到一个字典,该字典包含除与形式参数相对应的所有关键词参数之外的所有关键词参数。 这可以与形式为*name的形式参数组合,该形式参数接收一个元组,其中包含形式参数列表之外的位置参数。 (*name必须在**name之前出现。)例如,如果我们定义如下函数:

def cheeseshop(kind, *arguments, **keywords):
    print("-- Do you have any", kind, "?")
    print("-- I'm sorry, we're all out of", kind)
    for arg in arguments:
        print(arg)
    print("-" * 40)
    for kw in keywords:
        print(kw, ":", keywords[kw])

然后可以通过以下方式调用:

cheeseshop("Limburger", "It's very runny, sir.",
           "It's really very, VERY runny, sir.",
           shopkeeper="Michael Palin",
           client="John Cleese",
           sketch="Cheese Shop Sketch")

特殊参数(3.8新特性)

默认情况下,参数可以按位置或通过关键字显式传递给Python函数。 为了提高可读性和性能,限制参数传递的方式是有意义的,以便开发人员仅需查看函数定义即可确定是按位置,按位置或关键字还是按关键字传递参数。

def f(pos1, pos2, /, pos_or_kwd, *, kwd1, kwd2):
      -----------    ----------     ----------
        |             |                  |
        |        Positional or keyword   |
        |                                - Keyword only
         -- Positional only

若/和*不在函数参数定义中,则参数可以通过位置或关键字参数传递。
若/在参数定义中,则在/之前的参数只能通过位置参数传递,不能通过关键字参数传递。若*在参数定义中,则*之后的参数只能通过关键字参数传递。
示例:

>>> def standard_arg(arg):
...     print(arg)
...
>>> def pos_only_arg(arg, /):
...     print(arg)
...
>>> def kwd_only_arg(*, arg):
...     print(arg)
...
>>> def combined_example(pos_only, /, standard, *, kwd_only):
...     print(pos_only, standard, kwd_only)

standard_arg函数可以通过位置参数或关键字参数传递,pos_only_arg只能通过位置参数传递,kwd_only_arg只能通过关键字参数传递,而combined_example结合了前面示例。

总结:

作为指导:

  • 如果不希望用户使用参数名称,请使用仅位置参数。 当参数名称没有实际含义时,如果要在调用函数时强制执行参数的顺序,或者需要使用一些位置参数和任意关键字,此功能将非常有用。
  • 仅当名称具有含义且通过使用名称显式使函数定义更易于理解时,或者要防止用户依赖传递的参数的位置时,才应使用关键字。
  • 对于API,如果将来要修改参数的名称,请使用仅位置参数以防止破坏API的更改。
posted @ 2019-11-28 22:26  Jeffrey_Yang  阅读(276)  评论(0编辑  收藏  举报