Как игнорировать неожиданные аргументы ключевого слова, переданные функции?
Предположим, у меня есть какая-то функция, f
:
def f (a=None):
print a
Теперь, если у меня есть словарь, такой как dct = {"a":"Foo"}
, я могу вызвать f(**dct)
и получить результат Foo
.
Однако предположим, что у меня есть словарь dct2 = {"a":"Foo", "b":"Bar"}
. Если я позвоню f(**dct2)
я получу
TypeError: f() got an unexpected keyword argument 'b'
Справедливо. Однако в любом случае, в определении f
или при вызове его, Python должен просто игнорировать любые ключи, которые не являются именами параметров? Предпочтителен метод, который позволяет указывать значения по умолчанию.
Ответы
Ответ 1
В качестве дополнения к ответу, опубликованному @Bas, я бы предложил добавить аргументы kwargs (аргументы ключевого слова переменной длины) в качестве второго параметра функции
>>> def f (a=None, **kwargs):
print a
>>> dct2 = {"a":"Foo", "b":"Bar"}
>>> f(**dct2)
Foo
Это обязательно будет достаточно в случае
- просто игнорировать любые ключи, которые не являются именами параметров
- Тем не менее, ему не хватает значений параметров по умолчанию, что является хорошей особенностью, которую было бы неплохо сохранить
Ответ 2
Это можно сделать, используя **kwargs
, который позволяет собирать все аргументы ключевого слова undefined в файле dict:
def f(**kwargs):
print kwargs['a']
Быстрый тест:
In [2]: f(a=13, b=55)
13
EDIT Если вы все еще хотите использовать аргументы по умолчанию, вы сохраняете исходный аргумент со значением по умолчанию, но вы просто добавляете **kwargs
для поглощения всех остальных аргументов:
In [3]: def f(a='default_a', **kwargs):
...: print a
...:
In [4]: f(b=44, a=12)
12
In [5]: f(c=33)
default_a
Ответ 3
Если вы не можете изменить определение функции для получения неуточненных ** kwargs, вы можете отфильтровать словарь, который вы передаете с помощью аргументов ключевого слова, используя функцию argspec в более старых версиях python или метод проверки подписи в Python 3.6.
import inspect
def filter_dict(dict_to_filter, thing_with_kwargs):
sig = inspect.signature(thing_with_kwargs)
filter_keys = [param.name for param in sig.parameters.values() if param.kind == param.POSITIONAL_OR_KEYWORD]
filtered_dict = {filter_key:dict_to_filter[filter_key] for filter_key in filter_keys}
return filtered_dict
def myfunc(x=0):
print(x)
mydict = {'x':2, 'y':3}
filtered_dict = filter_dict(mydict, myfunc)
myfunc(**filtered_dict) # 2
myfunc(x=3) # 3