Python: meaning of a star * alone in function declaration

简介

看下面这个函数:

def compare(a, b, key):
    return a[key] > b[key]

对于需要比较的两个变量:

james = {'name': 'James', 'age': 20}
bob = {'name': 'Bob', 'age': 22}

下面这两个调用方法可以达到同样的效果:

james = {'name': 'James', 'age': 20}
bob = {'name': 'Bob', 'age': 22}
compare(james, bob, key='age')
compare(james, bob, 'age')

如果万一我们就是想要key只能以key='age'而不能以'age'传参,该怎么实现呢?这就是Python中参数里单个星号*的意义所在了。

Keyword-Only Arguments

对这个星号*的定义和描述在[PEP 3102]中。

星号可以以一个参数的形式出现在函数声明中的参数列表中,但星号之后的所有参数都必须有关键字(keyword),这样在函数调用时,星号*之后的所有参数都必须以keyword=value的形式调用,而不能以位置顺序调用。

例子

例一

def compare(a, b, *, key):
    return a[key] > b[key]

关键字key在星号*后,当我们以位置顺序调用时:

compare(james, bob, 'age')

会得到错误:

TypeError: compare() takes 2 positional arguments but 3 were given

而只有以:

compare(james, bob, key='age')

才会正确返回:

False

例二

接着上面那个,如果把星号*放在第一个参数位置呢:

def compare(*, a, b, key):
    return a[key] > b[key]

这时上面正确的调用此时也会返回:

TypeError: compare() takes 0 positional arguments but 2 positional arguments (and 1 keyword-only argument) were given

而只有通过:

result = compare(a=james, b=bob, key='age')

才能得到:

False

附注

Python中目前一共有4个这种参数中的特殊符号,即*[]/,可以在[PEP 436]中找到其简介。

/是Positional-Only Parameters,是和本文介绍的Keyword-Only Arguments正好相反的功能,但目前正处在草稿阶段,还没有列入标准,详细介绍在[PEP 457]中。

参考

PEP 436 -- The Argument Clinic DSL
PEP 457 -- Syntax For Positional-Only Parameters | Python.org
PEP 3102 -- Keyword-Only Arguments | Python.org
Python: What does the slash mean in the output of help(range)? - Stack Overflow