Получить внутреннюю функцию kwargs

Если у меня есть такая функция python:

def some_func(arg1, arg2, arg3=1, arg4=2):

Есть ли способ определить, какие аргументы были переданы по ключевому слову внутри функции?

ИЗМЕНИТЬ

Для тех, кто спрашивает, зачем я нуждаюсь в этом, у меня нет реальной причины, это произошло в разговоре, и любопытство стало лучше меня.

Ответы

Ответ 1

Нет, нет способа сделать это в коде Python с этой сигнатурой - если вам нужна эта информация, вам нужно изменить подпись функции.

Если вы посмотрите на API Python C, вы увидите, что аргументы фактического пути передаются в обычную функцию Python, всегда как кортеж плюс dict, то есть способ прямого отражения сигнатуры *args, **kwargs. Затем этот кортеж и dict анализируются на определенные позиционные аргументы и те, которые названы в сигнатуре, даже если они были переданы по имени, а *a и **kw, если они есть, принимают только "переполнение" от этого разбора, если есть - только в этот момент ваш код Python получает контроль, и к тому времени информация, которую вы запрашиваете (как прошли различные аргументы), больше не существует.

Чтобы получить запрошенную вами информацию, измените подпись на *a, **kw и сделайте свой собственный синтаксический анализ/проверку - это происходит "от яйца до омлета", т.е. определенная работа, но, безусловно, возможно, в то время как то, что вы ищете, будет "от омлета обратно к яйцу"... просто не выполнимо; -).

Ответ 2

Здесь мое решение через декораторы:

def showargs(function):
    def inner(*args, **kwargs):
        return function((args, kwargs), *args, **kwargs)
    return inner

@showargs
def some_func(info, arg1, arg2, arg3=1, arg4=2):
    print arg1,arg2,arg3,arg4
    return info

In [226]: some_func(1,2,3, arg4=4)
1 2 3 4
Out[226]: ((1, 2, 3), {'arg4': 4})

Возможно, есть способ очистить его дальше, но это кажется минимально навязчивым для меня и не требует изменения кода вызова.

Изменить: Чтобы на самом деле проверить, были ли определенные аргументы переданы по ключевому слову, выполните следующие действия внутри some_func:

args, kwargs = info
if 'arg4' in kwargs:
    print "arg4 passed as keyword argument"

Отказ от ответственности:, вам, вероятно, следует подумать, действительно ли вы заботитесь о том, как передавались аргументы. Весь этот подход может оказаться ненужным.

Ответ 3

В основном вы должны будете переопределить свою функцию:

def some_func(*args, **kwargs):

и сделайте маршалинг самостоятельно. Нет никакого способа рассказать разницу между пошаговыми позициями, по-ключевому слову и по умолчанию.

Ответ 4

Вы хотите знать, был ли arg3 1, потому что он был передан извне или потому, что он был значением по умолчанию? Нет, я не знаю, как это сделать. Основная причина, я подозреваю, что нет необходимости в таких знаниях. Обычно выполняется следующее:

>>> def func(a, b=None):
    if b is None:
# here we know that function was called as:
# func('spam') or func('spam', None) or func('spam', b=None) or func(a='spam', b=None)

        b = 42

Ответ 5

Просто сделайте это так:

def some_func ( arg1, arg2, arg3=None, arg4=None ):
    if arg3 is None:
        arg3 = 1 # default value
    if arg4 is None:
        arg4 = 2 # default value

    # do something

Таким образом вы можете видеть, когда что-то было установлено, и вы также можете работать с более сложными структурами по умолчанию (например, списки), не сталкиваясь с такими проблемами:

>>> def test( arg=[] ):
        arg.append( 1 )
        print( arg )
>>> test()
[1]
>>> test()
[1, 1]