Получить внутреннюю функцию 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]