LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 341|回复: 0

特殊参数

[复制链接]
发表于 2023-12-25 15:35:00 | 显示全部楼层 |阅读模式

特殊参数


默认情况下,参数可以按位置或显式关键字传递给 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 是最常见的形式,对调用方式没有任何限制,可以按位置也可以按关键字传递参数:

>>>
standard_arg(2)
2

standard_arg(arg=2)
2
第二个函数 pos_only_arg 的函数定义中有 /,仅限使用位置形参:

>>>
pos_only_arg(1)
1

pos_only_arg(arg=1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: pos_only_arg() got some positional-only arguments passed as keyword arguments: 'arg'
第三个函数 kwd_only_args 的函数定义通过 * 表明仅限关键字参数:

>>>
kwd_only_arg(3)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: kwd_only_arg() takes 0 positional arguments but 1 was given

kwd_only_arg(arg=3)
3
最后一个函数在同一个函数定义中,使用了全部三种调用惯例:

>>>
combined_example(1, 2, 3)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: combined_example() takes 2 positional arguments but 3 were given

combined_example(1, 2, kwd_only=3)
1 2 3

combined_example(1, standard=2, kwd_only=3)
1 2 3

combined_example(pos_only=1, standard=2, kwd_only=3)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: combined_example() got some positional-only arguments passed as keyword arguments: 'pos_only'
下面的函数定义中,kwds 把 name 当作键,因此,可能与位置参数 name 产生潜在冲突:

def foo(name, **kwds):
    return 'name' in kwds
调用该函数不可能返回 True,因为关键字 'name' 总与第一个形参绑定。例如:

>>>
foo(1, **{'name': 2})
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: foo() got multiple values for argument 'name'

加上 / (仅限位置参数)后,就可以了。此时,函数定义把 name 当作位置参数,'name' 也可以作为关键字参数的键:

>>>
def foo(name, /, **kwds):
    return 'name' in kwds

foo(1, **{'name': 2})
True
换句话说,仅限位置形参的名称可以在 **kwds 中使用,而不产生歧义。

小结

以下用例决定哪些形参可以用于函数定义:

def f(pos1, pos2, /, pos_or_kwd, *, kwd1, kwd2):
说明:

使用仅限位置形参,可以让用户无法使用形参名。形参名没有实际意义时,强制调用函数的实参顺序时,或同时接收位置形参和关键字时,这种方式很有用。

当形参名有实际意义,且显式名称可以让函数定义更易理解时,阻止用户依赖传递实参的位置时,才使用关键字。

对于 API,使用仅限位置形参,可以防止未来修改形参名时造成破坏性的 API 变动。


您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表