2008-10-20 2 views
167

Учитывая функцию Python:Попадая имена параметров методы в питоне

def aMethod(arg1, arg2): 
    pass 

Как я могу извлечь число и имена аргументов. То есть. учитывая, что у меня есть ссылка на func, я хочу func. [something] to return ("arg1", "arg2")

Сценарий использования для этого состоит в том, что у меня есть декоратор, и я хочу использовать аргументы метода в том же порядке, что и для фактической функции в качестве ключа. То есть. как бы декоратор взгляд, который напечатан «а, б», когда я называю aMethod («а», «б»)

+1

Для другого списка ответов на почти идентичный вопрос, см [этот другой StackOverflow пост] (http://stackoverflow.com/questions/582056/get-list-of-parameters-inside-python-function) – 2011-02-04 00:57:00

+1

Ваш заголовок вводит в заблуждение: когда говорят «метод» по слову «функция», обычно думают о методе класса. Для функции ваш выбранный ответ (от Jouni K. Seppanen) хорош. Но для метода (класса) он не работает и следует использовать решение для проверки (от Брайана). – 2012-08-17 12:46:41

ответ

278

Взгляните на модуль inspect - это проведет осмотр различных свойств объекта кода для вас.

>>> inspect.getargspec(aMethod) 
(['arg1', 'arg2'], None, None, None) 

Другие результаты - это имя переменных * args и ** kwargs и предоставленных по умолчанию значений. то есть.

>>> def foo(a,b,c=4, *arglist, **keywords): pass 
>>> inspect.getargspec(foo) 
(['a', 'b', 'c'], 'arglist', 'keywords', (4,)) 

Обратите внимание, что некоторые вызывающие вызовы не могут быть интроспективными в некоторых реализациях Python. Например, в CPython некоторые встроенные функции, определенные в C, не содержат метаданных об их аргументах. В результате вы получите ValueError в случае, если вы используете inspect.getargspec() со встроенной функцией.

Поскольку Python 3.3, вы также можете использовать в inspect.signature() для того, чтобы знать, вызов подписи отзывной объекта:

>>> inspect.signature(foo) 
<Signature (a, b, c=4, *arglist, **keywords)> 
86

В CPython, количество аргументов

aMethod.func_code.co_argcount 

и их имена в начало

aMethod.func_code.co_varnames 

Эти детали реализации CPython, так что это, вероятно, не работает в других реализациях Python, таких как IronPython и Jython.

Одним из переносных способов допустить «сквозные» аргументы является определение вашей функции с помощью подписи func(*args, **kwargs). Это широко используется в частности. matplotlib, где внешний интерфейс API передает множество аргументов ключевых слов API нижнего уровня.

+0

co_varnames работает со стандартным Python, но этот метод не является предпочтительным, так как он также отображает внутренние аргументы. – MattK 2010-09-28 16:39:58

+11

Почему бы не использовать aMethod.func_code.co_varnames [: aMethod.func_code.co_argcount]? – hochl 2011-03-02 14:13:03

+12

`func_code` теперь можно найти как` __code__` – 2015-07-24 20:09:39

13

Вот что-то я думаю, что будет работать для того, что вы хотите, используя декоратор.

class LogWrappedFunction(object): 
    def __init__(self, function): 
     self.function = function 

    def logAndCall(self, *arguments, **namedArguments): 
     print "Calling %s with arguments %s and named arguments %s" %\ 
         (self.function.func_name, arguments, namedArguments) 
     self.function.__call__(*arguments, **namedArguments) 

def logwrap(function): 
    return LogWrappedFunction(function).logAndCall 

@logwrap 
def doSomething(spam, eggs, foo, bar): 
    print "Doing something totally awesome with %s and %s." % (spam, eggs) 


doSomething("beans","rice", foo="wiggity", bar="wack") 

Run это, он даст следующий результат:

C:\scripts>python decoratorExample.py 
Calling doSomething with arguments ('beans', 'rice') and named arguments {'foo': 
'wiggity', 'bar': 'wack'} 
Doing something totally awesome with beans and rice. 
10

Я думаю, что вы ищете метод местных жителей -


In [6]: def test(a, b):print locals() 
    ...: 

In [7]: test(1,2)    
{'a': 1, 'b': 2} 
19

В методе декоратора, вы могут перечислять аргументы исходного метода таким образом:

import inspect, itertools 

def my_decorator(): 

     def decorator(f): 

      def wrapper(*args, **kwargs): 

       # if you want arguments names as a list: 
       args_name = inspect.getargspec(f)[0] 
       print(args_name) 

       # if you want names and values as a dictionary: 
       args_dict = dict(itertools.izip(args_name, args)) 
       print(args_dict) 

       # if you want values as a list: 
       args_values = args_dict.values() 
       print(args_values) 

Если **kwargs являются важными для вас, то это будет немного сложнее:

 def wrapper(*args, **kwargs): 

      args_name = list(OrderedDict.fromkeys(inspect.getargspec(f)[0] + kwargs.keys())) 
      args_dict = OrderedDict(list(itertools.izip(args_name, args)) + list(kwargs.iteritems())) 
      args_values = args_dict.values() 

Пример:

@my_decorator() 
def my_function(x, y, z=3): 
    pass 


my_function(1, y=2, z=3, w=0) 
# prints: 
# ['x', 'y', 'z', 'w'] 
# {'y': 2, 'x': 1, 'z': 3, 'w': 0} 
# [1, 2, 3, 0] 
3

Поскольку ответы староваты и должны были сделать некоторые изменения для создания его работать Python3, я добавляю свою версию:

def _get_args_dict(fn, args, kwargs): 
    args_names = fn.__code__.co_varnames[:fn.__code__.co_argcount] 
    return {**dict(zip(args_names, args)), **kwargs} 

метод возвращает словарь, содержащий как арг и kwargs.

-1

Как насчет dir() и vars()?

Кажется делает именно то, что спрашивается супер просто ...

(Изнутри функции/метода)

1

Обновление для ответа Брайана. Если функция в Python 3 имеет ключевое слово, только аргументы, то вам нужно использовать inspect.getfullargspec:

def yay(a, b=10, *, c=20, d=30): 
    pass 
inspect.getfullargspec(yay) 

дает это:

FullArgSpec(args=['a', 'b'], varargs=None, varkw=None, defaults=(10,), kwonlyargs=['c', 'd'], kwonlydefaults={'c': 20, 'd': 30}, annotations={}) 
2

Возвращает список имен аргументов, заботится о парциальных и регулярных функций :

def get_func_args(f): 
    if hasattr(f, 'args'): 
     return f.args 
    else: 
     return list(inspect.signature(f).parameters) 
4

Python 3.5+

D eprecationWarning: inspect.getargspec() является устаревшим, используйте inspect.signature() вместо

Так ранее:

func_args = inspect.getargspec(function).args 

Сейчас:

func_args = list(inspect.signature(function).parameters.keys()) 

для проверки:

'arg' in list(inspect.signature(function).parameters.keys()) 

Учитывая, что у нас есть функция 'function', которая принимает аргумент 'arg', это будет оцениваться как True, иначе как False.

Пример из питона консоли:

Python 3.6.0 (v3.6.0:41df79263a11, Dec 23 2016, 07:18:10) [MSC v.1900 32 bit (Intel)] on win32 
>>> import inspect 
>>> 'iterable' in list(inspect.signature(sum).parameters.keys()) 
True 
2

В питон 3. + с Signature объекта под рукой, простой способ, чтобы получить соответствие между именами ARGS до значений, использует метод bind() Сигнатура в!

Для примера здесь является декоратор для печати карты так:

import inspect 


def decorator(f): 
    def wrapper(*args, **kwargs): 
     bound_args = inspect.signature(f).bind(*args, **kwargs) 
     bound_args.apply_defaults() 
     print(dict(bound_args.arguments)) 

     return f(*args, **kwargs) 

    return wrapper 


@decorator 
def foo(x, y, param_with_default="bars", **kwargs): 
    pass 

foo(1, 2, extra="baz") 
# This wil print: {'kwargs': {'extra': 'baz'}, 'param_with_default': 'bars', 'y': 2, 'x': 1} 
Смежные вопросы