Распаковка аргументов ключевого слова, но только те, которые соответствуют функции

Допустим, у меня есть функция:

def foo(a = None, b=None, c=None): return "a:%s, b:%s, c:%s" % (a,b,c) 

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

 d = {'a':1, 'x':4, 'b':2, 'y':5} 

Если я вызову следующее, я получу ошибку, потому что «x» и «y» не являются аргументами в аргументе функции foo.

 foo(**d) # error 

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

Пожалуйста, исправьте меня, если моя аргумент / параметр терминологии отключен.

3 Solutions collect form web for “Распаковка аргументов ключевого слова, но только те, которые соответствуют функции”

@Ashwini Chaudhary имеет очень питоновский способ решения вашей проблемы. Однако для этого требуется изменить подпись вашей функции foo .

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

 arg_count = foo.func_code.co_argcount args = foo.func_code.co_varnames[:arg_count] args_dict = {} for k, v in d.iteritems(): if k in args: args_dict[k] = v foo(**args_dict) 
 def foo(a = None, b=None, c=None,**extras): return "a:%s, b:%s, c:%s" % (a, b, c) 

здесь **extras будет собирать все дополнительные аргументы имени / ключевого слова.

Интересный вопрос. Я думаю, что большинство людей в реальной жизни используют подход @Ashwini Chaudhary.

Я согласен с @Rodrigue в том, что есть моменты, когда вы не можете изменить сигнатуру вызова функции (возможно, какой- то модуль) .

Когда это произойдет, используйте декоратор функции

 from inspect import getargspec from funtools import wraps def allow_kwargs(foo): argspec = getargspec(foo) # if the original allows kwargs then do nothing if argspec.keywords: return foo @wraps(foo) def newfoo(*args, **kwargs): #print "newfoo called with args=%r kwargs=%r"%(args,kwargs) some_args = dict((k,kwargs[k]) for k in argspec.args if k in kwargs) return foo(*args, **some_args) return newfoo # with your function: @allow_kwargs def foo(a = None, b=None, c=None): return "a:%s, b:%s, c:%s " % (a,b,c) # with someone_elses function: from some_place import foo foo = allow_kwargs(foo) 

@wraps от @wraps держит строки __name__ и __doc__ в такте. Вы также можете:

  • посмотрите на FunctionMaker из модуля декораторов, но это должно быть более многоразовым подходом.
  • измените newfoo, чтобы не пропускать лишние ключи без ключевых слов.
  • вызывающий func. изменить вход
  • Обнаружение изменения файла без опроса
  • Python для Windows Extensions - что он делает?
  • Google App Engine говорит: «Должен пройти проверку подлинности». При попытке развернуть любое приложение
  • Повторение элементов списка n раз
  • python и sys.argv
  • Скомпилированы внутренние функции Python?
  • Как эффективно сопоставить строку с набором подстановочных строк?
  • Python - лучший язык программирования в мире.