web-dev-qa-db-ja.com

関数に渡される予期しないキーワード引数をどのように無視しますか?

関数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に伝えますか?デフォルトを指定できます。

31
rspencer

@Basが投稿した回答の拡張として、関数の2番目のパラメーターとしてkwargs引数(可変長キーワード引数)を追加することをお勧めします。

>>> def f (a=None, **kwargs):
    print a


>>> dct2 = {"a":"Foo", "b":"Bar"}
>>> f(**dct2)
Foo

これは必然的に十分です

  1. パラメータ名ではないキーを無視する
  2. ただし、パラメータのデフォルト値が不足しているため、保持しておくと便利な機能です。
24
Abhijit

これは **kwargs を使用して実行できます。これにより、未定義のキーワード引数をすべて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
13
Bas Swinckels

関数定義を変更して、指定されていない** kwargsを取得できない場合、pythonの古いバージョンのargspec関数または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
5
Aviendha