Можете ли вы перечислить аргументы ключевых слов, получаемые функцией Python?

У меня есть dict, который мне нужно передать ключ / значения в качестве аргументов ключевого слова. Например ..

d_args = {'kw1': 'value1', 'kw2': 'value2'} example(**d_args) 

Это работает отлично, но если в d_args dict есть значения, которые не принимаются функцией example , он, очевидно, умирает. Скажем, если def example(kw2): функция определена как def example(kw2):

Это проблема, так как я не контролирую ни генерацию d_args , ни функцию example . Они оба происходят из внешних модулей, а example принимает только некоторые ключевые слова-аргументы из dict.

В идеале я бы просто сделал

 parsed_kwargs = feedparser.parse(the_url) valid_kwargs = get_valid_kwargs(parsed_kwargs, valid_for = PyRSS2Gen.RSS2) PyRSS2Gen.RSS2(**valid_kwargs) 

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

5 Solutions collect form web for “Можете ли вы перечислить аргументы ключевых слов, получаемые функцией Python?”

Немного лучше, чем проверка объекта кода непосредственно и разработка переменных – использовать модуль проверки.

 >>> import inspect >>> def func(a,b,c=42, *args, **kwargs): pass >>> inspect.getargspec(func) (['a', 'b', 'c'], 'args', 'kwargs', (42,)) 

Если вы хотите узнать, может ли он быть вызван с определенным набором аргументов, вам нужны аргументы без заданного по умолчанию значения. Их можно получить:

 def getRequiredArgs(func): args, varargs, varkw, defaults = inspect.getargspec(func) if defaults: args = args[:-len(defaults)] return args # *args and **kwargs are not required, so ignore them. 

Тогда функция, чтобы рассказать, что вам не хватает в вашем конкретном dict:

 def missingArgs(func, argdict): return set(getRequiredArgs(func)).difference(argdict) 

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

 def invalidArgs(func, argdict): args, varargs, varkw, defaults = inspect.getargspec(func) if varkw: return set() # All accepted return set(argdict) - set(args) 

И поэтому полный тест, если он разрешен:

 def isCallableWithArgs(func, argdict): return not missingArgs(func, argdict) and not invalidArgs(func, argdict) 

(Это хорошо только при анализе аргументов python. Любые проверки времени выполнения для недопустимых значений в kwargs, очевидно, не могут быть обнаружены.)

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

 def func(one, two="value"): y = one, two return y print func.func_code.co_varnames[:func.func_code.co_argcount] 

Это связано с тем, что первые co_varnames всегда являются параметрами (следующие локальные переменные, например y в приведенном выше примере).

Итак, теперь у вас может быть функция:

 def getValidArgs(func, argsDict): '''Return dictionary without invalid function arguments.''' validArgs = func.func_code.co_varnames[:func.func_code.co_argcount] return dict((key, value) for key, value in argsDict.iteritems() if key in validArgs) 

Что вы тогда могли бы использовать так:

 >>> func(**getValidArgs(func, args)) 

EDIT : небольшое дополнение: если вам действительно нужны только аргументы ключевого слова для функции, вы можете использовать атрибут func_defaults для их извлечения:

 def getValidKwargs(func, argsDict): validArgs = func.func_code.co_varnames[:func.func_code.co_argcount] kwargsLen = len(func.func_defaults) # number of keyword arguments validKwargs = validArgs[-kwargsLen:] # because kwargs are last return dict((key, value) for key, value in argsDict.iteritems() if key in validKwargs) 

Теперь вы можете называть свою функцию известными аргументами, но извлекать kwargs, например:

 func(param1, param2, **getValidKwargs(func, kwargsDict)) 

Это предполагает, что func использует в своей сигнатуре **kwargs *args или **kwargs .

В Python 3.0:

 >>> import inspect >>> import fileinput >>> print(inspect.getfullargspec(fileinput.input)) FullArgSpec(args=['files', 'inplace', 'backup', 'bufsize', 'mode', 'openhook'], varargs=None, varkw=None, defaults=(None, 0, '', 0, 'r', None), kwonlyargs=[], kwdefaults=None, annotations={}) 

Расширение ответа DzinX:

 argnames = example.func_code.co_varnames[:func.func_code.co_argcount] args = dict((key, val) for key,val in d_args.iteritems() if key in argnames) example(**args) 

Для решения Python 3 вы можете использовать inspect.signature и фильтровать в соответствии с теми параметрами, о которых вы хотели бы узнать.

Взятие примерной функции с параметрами positional или keyword, keyword-only, var positional и var key:

 def spam(a, b=1, *args, c=2, **kwargs): print(a, b, args, c, kwargs) 

Вы можете создать для него объект подписи:

 from inspect import signature sig = signature(spam) 

а затем фильтруйте с помощью списка, чтобы узнать нужные детали:

 >>> # positional or keyword >>> [p.name for p in sig.parameters.values() if p.kind == p.POSITIONAL_OR_KEYWORD] ['a', 'b'] >>> # keyword only >>> [p.name for p in sig.parameters.values() if p.kind == p.KEYWORD_ONLY] ['c'] 

и, аналогично, для позиций var с использованием p.VAR_POSITIONAL и ключевого слова var с VAR_KEYWORD .

Кроме того, вы можете добавить предложение к if, чтобы проверить, существует ли значение по умолчанию, если p.default равен p.empty .

  • Как получить доступ к свойствам суперклассов Python, например, через __class __.__ dict__?
  • Как я могу перечислить методы в модуле Python 2.5?
  • Как функция может быть устойчивой к себе?
  • Как обращаться к имени метода с помощью метода в Python?
  • В python есть ли способ узнать, реализует ли объект «реализует интерфейс», прежде чем передать его функции?
  • Локальная интроспекция в python3?
  • Как перечислить все поля класса в Python (и без методов)?
  • Как выполнить интроспекцию объекта в Python 2.x?
  • Python - лучший язык программирования в мире.