__kwdefaults__在定义了** kwargs的python3函数上为空

时间:2019-01-02 15:27:03

标签: python-3.x

python 3.6.8

def xx(test=1, sim=0.2):
    return test + sim

print(xx.__defaults__, xx.__kwdefaults__)

我得到以下输出:

Python 3.6.8 (default, Dec 29 2018, 10:04:55) 
Type 'copyright', 'credits' or 'license' for more information
IPython 7.1.1 -- An enhanced Interactive Python. Type '?' for help.

Out[1]: (1, 0.2) None

我希望

Out[1]: None {'test': 1, 'sim': 0.2}

但是如果我更改

def xx(*args, arg1, test=1, sim=0.2):
    return test + sim


print(xx.__defaults__, xx.__kwdefaults__)

我得到了我想要的东西:

Python 3.6.8 (default, Dec 29 2018, 10:04:55) 
Type 'copyright', 'credits' or 'license' for more information
IPython 7.1.1 -- An enhanced Interactive Python. Type '?' for help.

Out[1]: None {'test': 1, 'sim': 0.2}

但是我设计的函数应该只接受关键字类型的参数,即不接受*args

为什么这样的行为?

我需要获取参数列表(参数名称)和关键字参数的默认值。

我想念什么?

3 个答案:

答案 0 :(得分:3)

  

我的功能在设计上应该只接受关键字类型的参数,即不接受* args

使用*明确地说出来,然后您将获得所需的输出:

def foo(*, test=1): pass

print(foo.__kwdefaults__)
# {'test': 1}

def foo(test=1)不会test设为仅关键字的参数。它只是给test提供默认值,但是test仍可以作为位置参数传递,即foo(2)

答案 1 :(得分:2)

__kwdefaults__仅适用于唯一被关键字接受的参数; per the docs

  

__defaults__-位置或关键字参数的任何默认值的元组   __kwdefaults__-仅关键字参数的所有默认值的映射

因此,如果可以 按位置传递它们,则它们会出现在__defaults__中。如果要将参数设为仅关键字而不接受位置参数,请添加一个空的*参数(Python 3中新增; Python 2中不可用):

def xx(*, test=1, sim=0.2):
    return test + sim

*之后的所有参数只能通过关键字传递。

答案 2 :(得分:2)

看着data model docs,我们看到__kwdefaults__

  

包含仅关键字参数默认值的字典。

仅关键字参数在PEP3102中引入。简而言之,它们是argument list*args或普通*之后的任何参数。

因此,尽管test中的simdef xx(test=1, sim=0.2):在实际的函数调用中可能由关键字指定,但实际上它们被命名为位置参数,而不是关键字-仅。

一种简单的解决方法是使用*将其设置为仅关键字:

def xx(*, test=1, sim=0.2):

如果您需要获取命名参数的默认值,也可以使用inspect模块:

from inspect import signature, Parameter

defaults = {p.name: p.default for p in signature(xx).parameters if p.default is not Parameter.empty}

想法来自here

此解决方案的优点是它将在一个位置报告位置默认值和关键字默认值。这样,您不必将功能限制为仅接受关键字参数。