Как отобразить функцию на все значения аргумента, как список? но иметь явные имена аргументов в определении функции
Я хочу определить функцию, используя явные имена аргументов ff(a,b,c)
в определении функции, но я также хочу отобразить функцию на все аргументы, чтобы получить список:
ff(a,b,c):
return list(map(myfunc,[a,b,c]))
Однако я не хочу явно писать имена параметров внутри функции как a,b,c. Я хочу сделать это как
ff(a,b,c):
return list(map(myfunc,getArgValueList()))
getArgValueList()
получит значения аргументов в порядке и сформирует список. Как это сделать? Есть ли встроенная функция, как getArgValueList()
?
2 ответа
То, что вы пытаетесь сделать, невозможно без безобразных хаков. Вы либо берете *args
и получить последовательность значений параметров, которые вы можете использовать как args
:
def ff(*args):
return list(map(myfunc, args))
... или вы берете три явных параметра и используете их по имени:
def ff(a, b, c):
return list(map(myfunc, (a, b, c)))
... но это одно или другое, а не оба.
Конечно, вы можете поместить эти значения в последовательность самостоятельно, если хотите:
def ff(a, b, c):
args = a, b, c
return list(map(myfunc, args))
... но я не уверен, что это покупает тебя.
Если вы действительно хотите знать, как написать getArgValueList
в любом случае, я объясню, как это сделать. Однако, если вы хотите сделать свой код более читабельным, более эффективным, более идиоматичным, более простым для понимания, более кратким или почти чем-либо еще, это будет иметь прямо противоположный эффект. Единственная причина, по которой я могу себе представить, что делать что-то подобное, это то, что вам пришлось генерировать функции динамически или что-то в этом роде, и даже тогда я не могу придумать причину, по которой вы не могли бы просто использовать *args
, Но если вы настаиваете:
def getArgValueList():
frame = inspect.currentframe().f_back
code = frame.f_code
vars = code.co_varnames[:code.co_argcount]
return [frame.f_locals[var] for var in vars]
Если вы хотите знать, как это работает, большинство из них находится в inspect
модульные документы:
currentframe()
получает текущий кадр - кадрgetArgValueList
,f_back
получает родительский кадр - кадр того, кто вызвалgetArgValueList
,f_code
получает объект кода, скомпилированный из тела функции того, кто вызвалgetArgValueList
,co_varnames
это список всех локальных переменных в этом теле, начиная с параметров.co_argcount
это число явных позиционных параметров или ключевых слов.f_locals
это диктат с копиейlocals()
среда кадра.
Это, конечно, работает только для функции, которая не требует *args
, аргументы только для ключевых слов, или **kwargs
, но вы можете расширить его, чтобы работать на них, а также немного работы. (Увидеть co_kwonlyargcount
, co_flags
, CO_VARARGS
, а также CO_VARKEYWORDS
для деталей.)
Кроме того, это работает только для CPython, но не для большинства других интерпретаторов. и он может сломаться в какой-то будущей версии, потому что он довольно явно полагается на детали реализации интерпретатора.
*args
Конструкция выдаст вам аргументы в виде списка:
>>> def f(*args): return list(map(lambda x:x+1, args))
>>> f(1,2,3)
[2, 3, 4]
Если вы связаны с подписью f
вам придется использовать inspect
модуль:
import inspect
def f(a, b,c):
f_locals = locals()
values = [f_locals[name] for name in inspect.signature(f).parameters]
return list(map(lambda x:x+1, values))
inspect.signature(f).parameters
выдает список аргументов в правильном порядке. Значения в locals()
,