获取函数参数的默认值?
Posted
技术标签:
【中文标题】获取函数参数的默认值?【英文标题】:Get a function argument's default value? 【发布时间】:2022-01-05 09:35:53 【问题描述】:对于这个功能
def eat_dog(name, should_digest=True):
print "ate dog named %s. Digested, too? %" % (name, str(should_digest))
我想在函数外部读取它的参数和任何附加的默认值。所以对于这个具体的例子,我想知道name
没有默认值(即它是一个必需的参数)并且True
是should_digest
的默认值。
我知道inspect.getargspec()
,它确实为我提供了有关参数和默认值的信息,但我发现两者之间没有任何联系:
ArgSpec(args=['name', 'should_digest'], varargs=None, keywords=None, defaults=(True,))
从这个输出我怎么知道True
(在defaults
元组中)是should_digest
的默认值?
此外,我知道解决问题的“请求宽恕”模型,但不幸的是,该错误的输出不会告诉我缺少的参数的名称:
>>> eat_dog()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: eat_dog() takes at least 1 argument (0 given)
为了提供上下文(我为什么要这样做),我通过 JSON API 公开模块中的函数。如果调用者省略了某些函数参数,我想返回一个特定的错误来命名被省略的特定函数参数。如果客户端省略了参数,但函数签名中提供了默认值,我想使用该默认值。
【问题讨论】:
【参考方案1】:Python3.x
在 python3.x 世界中,您可能应该使用 Signature
对象:
import inspect
def get_default_args(func):
signature = inspect.signature(func)
return
k: v.default
for k, v in signature.parameters.items()
if v.default is not inspect.Parameter.empty
Python2.x(旧答案)
参数/默认值可以组合为:
import inspect
a = inspect.getargspec(eat_dog)
zip(a.args[-len(a.defaults):],a.defaults)
这里a.args[-len(a.defaults):]
是具有默认值的参数,显然a.defaults
是相应的默认值。
您甚至可以将zip
的输出传递给dict
构造函数,并创建一个适合关键字解包的映射。
查看文档,此解决方案仅适用于 python2.6 或更高版本,因为我假设 inspect.getargspec
返回一个命名元组。早期版本返回一个正则元组,但它会很容易进行相应的修改。这是一个适用于旧(和新)版本的版本:
import inspect
def get_default_args(func):
"""
returns a dictionary of arg_name:default_values for the input function
"""
args, varargs, keywords, defaults = inspect.getargspec(func)
return dict(zip(args[-len(defaults):], defaults))
想一想:
return dict(zip(reversed(args), reversed(defaults)))
也可以,而且对某些人来说可能更直观。
【讨论】:
@Tadeck -- 我必须支持你的。我只是在猜测如何将它们结合起来,直到我看到你的帖子证实了我的怀疑。 @Tadeck 你能解释一下这是如何工作的吗?我对发生的事情有点困惑。 @skyler -- 你知道zip
函数吗?哪部分不明白。如果你能告诉我什么让你感到困惑,我会很乐意改进答案。
@mgilson 我想我现在明白了。具有默认值的 args 不能与没有默认值的 args 穿插,因此将默认值映射到 args 列表,从最后一个参数开始并向后移动,正确连接两者。
@skyler -- 没错。我自己说得再好不过了。【参考方案2】:
您可以将inspect
模块与它的getargspec
function 一起使用:
inspect.getargspec(func)
获取 Python 函数参数的名称和默认值。返回四个事物的
tuple
:(args, varargs, keywords, defaults)
。args
是参数名称列表(它可能包含嵌套列表)。varargs
和keywords
是*
和**
参数或None
的名称。defaults
是默认参数值的元组 或None
(如果没有默认参数);如果这个元组有n
元素,它们对应于args
中列出的最后一个n
元素。
有关如何检索参数名称及其默认值的确切代码,请参阅 mgilson's answer。
【讨论】:
【参考方案3】:根据您的具体需要,您可能不需要inspect
模块,因为您可以检查函数的__defaults__
属性:
>>> eat_dog.__defaults__
(True,)
>>> eat_dog.__code__.co_argcount
2
>>> eat_dog.__code__.co_varnames
('name', 'should_digest')
>>>
>>> eat_dog.__kwdefaults__
>>> eat_dog.__code__.co_kwonlyargcount
0
【讨论】:
【参考方案4】:对于那些正在寻找使用mgilson's 答案获取特定默认参数的版本的人。
value = signature(my_func).parameters['param_name'].default
这是一个完整的工作版本,在Python 3.8.2
完成
from inspect import signature
def my_func(a, b, c, param_name='apple'):
pass
value = signature(my_func).parameters['param_name'].default
print(value == 'apple') # True
【讨论】:
【参考方案5】:处理仅关键字参数(并且因为默认值和 kwonlydefaults 可以是 None
):
spec = inspect.getfullargspec(func)
defaults = dict(zip(spec.args[::-1], (spec.defaults or ())[::-1]))
defaults.update(spec.kwonlydefaults or )
【讨论】:
是的。 +1 指出这一点。我最初的答案是在 python3.x 流行之前写的。事实证明,现在甚至还有一种 更好的 方法可以使用 Signature 对象(我已将其添加到我的原始答案中)来处理这个问题【参考方案6】:在python中,所有有默认值的参数都在没有默认值的参数之后。所以映射应该从头开始,直到你用完默认值列表。因此逻辑:
dict(zip(reversed(args), reversed(defaults)))
给出正确映射的默认值。
【讨论】:
以上是关于获取函数参数的默认值?的主要内容,如果未能解决你的问题,请参考以下文章