78

对于这个功能

def eat_dog(name, should_digest=True):
    print "ate dog named %s. Digested, too? %" % (name, str(should_digest))

我想在函数外部读取它的参数和附加的任何默认值。所以对于这个特定的例子,我想知道它name没有默认值(即它是一个必需的参数),这Trueshould_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 公开模块中的函数。如果调用者省略了某些函数参数,我想返回一个特定的错误来命名被省略的特定函数参数。如果客户端省略了参数,但函数签名中提供了默认值,我想使用该默认值。

4

6 回答 6

127

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是相应的默认值。

您甚至可以将 的输出传递zipdict构造函数并创建适合关键字解包的映射。


查看文档,此解决方案仅适用于 python2.6 或更高版本,因为我假设它inspect.getargspec返回一个命名的 tuple。早期版本返回一个常规的 tuple,但很容易进行相应的修改。这是一个适用于旧(和新)版本的版本:

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)))

也可以工作,并且对某些人来说可能更直观。


于 2012-09-27T17:46:14.617 回答
11

您可以使用inspect模块及其getargspec功能

inspect.getargspec(func)

获取Python 函数参数的名称和默认值tuple返回四样东西中的一个: (args, varargs, keywords, defaults). args是参数名称的列表(它可能包含嵌套列表)。varargskeywords***参数或的名称Nonedefaults是默认参数值的元组,或者None如果没有默认参数;如果此元组有n元素,则它们对应于 中n列出的最后一个元素args

有关如何检索参数名称及其默认值的确切代码,请参阅mgilson 的答案。

于 2012-09-27T17:46:14.380 回答
7

根据您的具体需要,您可能不需要该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 
于 2020-01-28T10:15:38.967 回答
5

对于那些正在寻找一个版本来获取具有mgilson答案的特定默认参数的人。

    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

于 2020-04-28T13:30:11.673 回答
2

照顾仅限关键字的参数(并且因为 defaults 和 kwonlydefaults 可以是None):

spec = inspect.getfullargspec(func)
defaults = dict(zip(spec.args[::-1], (spec.defaults or ())[::-1]))
defaults.update(spec.kwonlydefaults or {})
于 2016-12-13T19:05:24.523 回答
1

在python中,所有具有默认值的参数都在没有默认值的参数之后。所以映射应该从头开始,直到你用完默认值列表。因此逻辑:

dict(zip(reversed(args), reversed(defaults)))

给出正确映射的默认值。

于 2014-11-22T02:29:06.957 回答