Подтвердить что ты не робот

Получение всех аргументов и значений, переданных функции

У меня есть функция Python, fetch_data, которая идет и удаляет удаленный API, захватывает некоторые данные и возвращает их в объект ответа. Это выглядит примерно так:

def fetch_data(self, foo, bar, baz, **kwargs):
    response = Response()
    # Do various things, get some data
    return response

Теперь, возможно, что данные ответа говорят: "У меня больше данных, позвоните мне с добавленным параметром page, чтобы получить больше". Таким образом, мне хотелось бы сохранить "Метод вызова" (функция, параметры) в объекте ответа, поэтому я могу иметь Response.get_more(), который смотрит на сохраненную функцию и параметры, и снова вызывает функцию (почти ) те же параметры, возвращая новый Response

Теперь, если fetch_data был определен как fetch_data(*args, **kwargs), я мог бы просто сохранить (fetch_data, args, kwargs) в Response. Однако мне нужно self, foo, bar и baz беспокоиться - я мог бы просто сохранить (fetch_data, foo, bar, baz, kwargs), но это очень нежелательное количество повторений.

По сути, я пытаюсь выяснить, как изнутри функции получить полностью заполненные *args и **kwargs, включая функцию с параметрами.

4b9b3361

Ответ 1

По сути, я пытаюсь выяснить, как изнутри функции получить полностью заполненные * args и ** kwargs, включая функцию с параметрами.

Как сохранить аргументы через locals() в начале функции?

def my_func(a, *args, **kwargs):
    saved_args = locals()
    print("saved_args is", saved_args)
    local_var = 10
    print("saved_args is", saved_args)
    print("But locals() is now", locals())

my_func(20, 30, 40, 50, kwarg1='spam', kwarg2='eggs')

Он выводит этот результат:

saved_args is {'a': 20, 'args': (30, 40, 50), 'kwargs': {'kwarg1': u'spam', 'kwarg2': u'eggs'}}
saved_args is {'a': 20, 'args': (30, 40, 50), 'kwargs': {'kwarg1': u'spam', 'kwarg2': u'eggs'}}
But locals is now {'a': 20, 'saved_args': {...}, 'args': (30, 40, 50), 'local_var': 10, 'kwargs': {'kwarg1': u'spam', 'kwarg2': u'eggs'}}

Совет шляпы: fooobar.com/questions/131841/...

Ответ 2

Не то, что я сделал бы, но вы могли бы использовать inspect.getargspec для анализа аргументов, которые использует ваш метод:

>>> import inspect
>>> def foobar(foo, bar, baz):
...     return inspect.getargspec(foobar)
... 
>>> foobar(1, 2, 3)
ArgSpec(args=['foo', 'bar', 'baz'], varargs=None, keywords=None, defaults=None)

Затем это можно объединить с locals(), чтобы перестроить ваши аргументы:

>>> def foobar(foo, bar, baz):
...     return [locals()[arg] for arg in inspect.getargspec(foobar).args]
... 
>>> foobar(1, 2, 3)
[1, 2, 3]

Тем не менее, вам действительно нужна такая магия при создании дополнительных декораторов функций и т.п. Я думаю, что это переполняет здесь.

Ответ 3

Я думаю, что более Pythonic-способ состоит в том, чтобы превратить вашу функцию в генератор, выборку и yield данные, пока сервер сохраняет возвращаемые данные.

Это должно привести к аккуратному коду и позволит вам перешагнуть все сложности сохранения аргументов через итерации (Python будет волшебным образом делать это за вас: -))

Ответ 4

Я не уверен, что это именно то, что вы хотите, но locals() предоставляет словарь локальных переменных.

>>> def foo(bar, toto):
...     print(locals())
...
>>> foo(3,'sometext')
{'toto': 'sometext', 'bar': 3}

Ответ 5

inspect.getargspec устарел с версии 3.0. Используйте signature() и объект подписи, которые обеспечивают лучший интерфейс для просмотра вызовов.

>>> from inspect import signature
>>> def foo(a, *, b:int, **kwargs):
...     pass

>>> sig = signature(foo)

>>> str(sig)
'(a, *, b:int, **kwargs)'

>>> str(sig.parameters['b'])
'b:int'

>>> sig.parameters['b'].annotation
<class 'int'>

Ответ 6

import inspect

def f(x, y):
    print(
        inspect.getargvalues(inspect.currentframe())
    )

f(1, 2)

Результат:
ArgInfo(args=['x', 'y'], varargs=None, keywords=None, locals={'y': 2, 'x': 1})

Ответ 7

kwargs не будет иметь "foo", "bar" или "bad" в качестве ключей, поэтому вы можете добавить эти записи (w/their values) в kwargs и просто сохранить (fetch_data, kwargs).