Если у меня есть функция Python как так:
def some_func(arg1, arg2, arg3=1, arg4=2):
Существует ли способ определить, какие аргументы были переданы ключевым словом из функции?
Править
Для тех, которые спрашивают, почему мне нужно это, у меня нет настоящей причины, это подошло в разговоре, и любопытство взяло верх надо мной.
Нет, нет способа сделать это в коде Python с этой подписью - если вам нужна эта информация, вам необходимо изменить подпись функции.
Если вы посмотрите на Python C API, вы увидите, что фактические способы аргументов передаются в нормальную функцию Python, всегда в качестве корки плюс Dict - то есть способ, которым является прямое отражение подписи * args, ** kwargs
. То, что кортеж и Dict затем проанализируются в конкретные позиционные аргументы и те, которые называются подписью, даже если они были переданы по имени, а * A
и ** KW
, если присутствуют , только возьмите «переполнение» от этого анализа, если таковые имеются - только в данный момент ваш код Python Get Control, и к тому, что информация, которую вы запрашиваете (, как были пройдены различные ARGS) еще больше нет.
Чтобы получить запрошенную вами информацию, поэтому измените подпись на * A, ** кВт
и сделайте свой собственный разбор / проверку - это происходит «из яйца до омлета», то есть Определенное количество работы, но, безусловно, осуществимо, в то время как то, что вы ищете, пойдут «от омлета обратно к яйцу» ... просто не осуществимо ;-).
Просто сделайте это так:
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]
Хотите знать, был ли 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
Вот мое решение через декораторы:
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})
может быть способ убрать это дальше, но это кажется минимально навязчивым для меня и не требует изменений в вызове.
Редактировать: На самом деле тестировать, если конкретные ARGS были переданы по ключевому слову, то сделайте что-то вроде следующего внутри quey_func:
args, kwargs = info
if 'arg4' in kwargs:
print "arg4 passed as keyword argument"
Отказ от ответственности: Вы, вероятно, должны учитывать, действительно ли вы заботитесь о том, как аргументы были переданы. Весь весь подход может быть ненужным.
Тебе в значительной степени придется переопределить вашу функцию:
def some_func(*args, **kwargs):
и сделать маршал себя. Там нет способа рассказать разницу между Pass-by-by-Position, Pass-by-limited и по умолчанию.