Подтвердить что ты не робот

Получить значение параметра аргумента функции?

Для этой функции

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)

Чтобы дать контекст (почему я хочу это сделать), я подвергаю функции в модуле над API JSON. Если вызывающий абонент пропускает определенные аргументы функции, я хочу вернуть определенную ошибку, которая называет аргумент конкретной функции, который был опущен. Если клиент опускает аргумент, но там есть значение по умолчанию, указанное в сигнатуре функции, я хочу использовать это значение по умолчанию.

4b9b3361

Ответ 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)))

также будет работать и может быть более интуитивным для некоторых людей.


Ответ 2

Вы можете использовать модуль inspect с getargspec function:

inspect.getargspec(func)

Получите имена и значения по умолчанию аргументов функций Python. Возвращается A tuple из четырех вещей: (args, varargs, keywords, defaults). args - список имен аргументов (он может содержать вложенные списки). varargs и keywords - имена аргументов * и ** или None. defaults является кортежем значений аргументов по умолчанию или None, если нет аргументов по умолчанию; если этот набор имеет элементы n, они соответствуют последним n элементам, перечисленным в args.

См. ответ mgilson для точного кода о том, как получить имена аргументов и их значения по умолчанию.

Ответ 3

В python все аргументы со значением по умолчанию появляются после аргументов без значения по умолчанию. Поэтому отображение должно начинаться с конца, пока вы не исчерпаете список значений по умолчанию. Следовательно, логика:

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

дает правильно отображаемые значения по умолчанию.

Ответ 4

чтобы заботиться только о args (только потому, что значения по умолчанию и kwonlydefaults могут быть None):

spec = inspect.getfullargspec(func)
defaults = dict(zip(spec.args[::-1], (spec.defaults or ())[::-1]))
defaults.update(spec.kwonlydefaults or {})