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

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

0 голосов
/ 14 мая 2018

То, что вы пытаетесь сделать, невозможно без безобразных хаков. Вы либо берете *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, но не для большинства других интерпретаторов. и он может сломаться в какой-то будущей версии, потому что он довольно явно полагается на детали реализации интерпретатора.

0 голосов
/ 14 мая 2018

Конструкция *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().

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...