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

Я хочу определить функцию, используя явные имена аргументов 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(),

Другие вопросы по тегам