デフォルト値に関しては、Pythonで**kwargs
を使用する適切な方法は何ですか?
kwargs
は辞書を返しますが、デフォルト値を設定する最善の方法は何ですか、それともありますか?辞書としてアクセスするだけでいいのですか。 get関数を使う?
class ExampleClass:
def __init__(self, **kwargs):
self.val = kwargs['val']
self.val2 = kwargs.get('val2')
簡単な質問ですが、良いリソースが見つかりません。私が見たことのあるコードでは、人々がさまざまな方法でそれを行いますが、何を使うべきかを知るのは困難です。
辞書にないキーのデフォルト値をget()
に渡すことができます。
self.val2 = kwargs.get('val2',"default value")
しかし、特定のデフォルト値を持つ特定の引数を使用することを計画している場合、まず最初に名前付き引数を使用しないでください。
def __init__(self, val2="default value", **kwargs):
ほとんどの答えはそれを言っていますが、例えば、
def f(**kwargs):
foo = kwargs.pop('foo')
bar = kwargs.pop('bar')
...etc...
「と同じ」
def f(foo=None, bar=None, **kwargs):
...etc...
本当じゃない。後者の場合、f
はf(23, 42)
として呼び出すことができますが、前者の場合は名前付き引数only-位置呼び出しを受け付けません。多くの場合、発信者に最大限の柔軟性を与えたいため、ほとんどの回答が主張するように、2番目の形式が望ましいです。しかし、常にそうであるとは限りません。通常は数個しか渡されない多くのオプションパラメータを受け入れる場合、名前付き引数の使用を強制することは(呼び出しサイトでの事故や判読不能なコードを避けるための)素晴らしいアイデアかもしれません-threading.Thread
は例です。最初の形式は、Python 2での実装方法です。
イディオムは非常に重要なので、Python 3では特別なサポート構文があります:def
シグネチャの単一の*
の後のすべての引数はキーワードのみです。つまり、位置引数として渡されますが、名前付き引数としてのみ渡されます。したがって、Python 3では、上記を次のようにコーディングできます。
def f(*, foo=None, bar=None, **kwargs):
...etc...
実際、Python 3では、オプションではないキーワードのみの引数さえ持つことができます(デフォルト値のないもの)。
ただし、Python 2には長年の生産的生命が残っているため、Python 2で実装できるテクニックとイディオムを忘れてくださいnotをお勧めしますPython 3の言語で直接サポートされているデザインアイデア!
私はこのようなことを提案します
def testFunc( **kwargs ):
options = {
'option1' : 'default_value1',
'option2' : 'default_value2',
'option3' : 'default_value3', }
options.update(kwargs)
print options
testFunc( option1='new_value1', option3='new_value3' )
# {'option2': 'default_value2', 'option3': 'new_value3', 'option1': 'new_value1'}
testFunc( option2='new_value2' )
# {'option1': 'default_value1', 'option3': 'default_value3', 'option2': 'new_value2'}
そして、好きなように値を使います。
dictionaryA.update(dictionaryB)
はdictionaryB
の内容をdictionaryA
に追加して重複するキーを上書きします。
あなたがやりたい
self.attribute = kwargs.pop('name', default_value)
または
self.attribute = kwargs.get('name', default_value)
pop
を使用している場合は、偽の値が送信されているかどうかを確認し、適切な処置を取ります(存在する場合)。
** kwargsとデフォルト値を使うのは簡単です。しかし、時には、そもそも** kwargsを使うべきではありません。
この場合、** kwargsを実際には最大限に活用していません。
class ExampleClass( object ):
def __init__(self, **kwargs):
self.val = kwargs.get('val',"default1")
self.val2 = kwargs.get('val2',"default2")
上記は「なぜ迷惑なのか」です。宣言。それはと同じです
class ExampleClass( object ):
def __init__(self, val="default1", val2="default2"):
self.val = val
self.val2 = val2
** kwargsを使用している場合、キーワードは単なるオプションではなく条件付きです。単純なデフォルト値よりも複雑な規則があります。
** kwargsを使用している場合、通常は次のようなものを意味します。単純なデフォルトは適用されません。
class ExampleClass( object ):
def __init__(self, **kwargs):
self.val = "default1"
self.val2 = "default2"
if "val" in kwargs:
self.val = kwargs["val"]
self.val2 = 2*self.val
Elif "val2" in kwargs:
self.val2 = kwargs["val2"]
self.val = self.val2 / 2
else:
raise TypeError( "must provide val= or val2= parameter values" )
引数の数が不明な場合は**kwargs
が使用されるので、なぜこれをしないのですか?
class Exampleclass(object):
def __init__(self, **kwargs):
for k in kwargs.keys():
if k in [acceptable_keys_list]:
self.__setattr__(k, kwargs[k])
これは別のアプローチです:
def my_func(arg1, arg2, arg3):
... so something ...
kwargs = {'arg1': 'Value One', 'arg2': 'Value Two', 'arg3': 'Value Three'}
# Now you can call the function with kwargs like this:
my_func(**kwargs)
こんなことができる
class ExampleClass:
def __init__(self, **kwargs):
arguments = {'val':1, 'val2':2}
arguments.update(kwargs)
self.val = arguments['val']
self.val2 = arguments['val2']
Pythonで**kwargs
をデフォルト値にするための適切な方法は、以下に示すように辞書メソッドsetdefault
を使用することです。
class ExampleClass:
def __init__(self, **kwargs):
kwargs.setdefault('val', value1)
kwargs.setdefault('val2', value2)
このように、ユーザがキーワードargs
に 'val'または 'val2'を渡すと、それらが使用されます。それ以外の場合は、設定されているデフォルト値が使用されます。
これを* argsと組み合わせたい場合は、定義の最後に* argsと** kwargsを付けておく必要があります。
そう:
def method(foo, bar=None, *args, **kwargs):
do_something_with(foo, bar)
some_other_function(*args, **kwargs)
@AbhinavGuptaと@Steefはupdate()
を使うことを提案しました。これは大きな引数リストを処理するのに非常に役立つことがわかりました。
args.update(kwargs)
ユーザーが偽の/サポートされていない引数を渡していないことを確認したい場合はどうなりますか? @VinaySajipは、pop()
は引数のリストを繰り返し処理するために使用できることを指摘しました。そして、残りの引数は偽物です。いいね。
これを行うためのもう1つの方法があります。これは、update()
を使用するという単純な構文を維持します。
# kwargs = dictionary of user-supplied arguments
# args = dictionary containing default arguments
# Check that user hasn't given spurious arguments
unknown_args = user_args.keys() - default_args.keys()
if unknown_args:
raise TypeError('Unknown arguments: {}'.format(unknown_args))
# Update args to contain user-supplied arguments
args.update(kwargs)
unknown_args
は、デフォルトでは発生しない引数の名前を含むset
です。
** kwargsはキーワード引数をいくつでも追加する自由を与えます。デフォルト値を設定できるキーのリストがあるかもしれません。しかし、不特定多数のキーにデフォルト値を設定することは不要のようです。最後に、インスタンス属性としてキーを持つことが重要かもしれません。だから、私はこれを次のようにするでしょう:
class Person(object):
listed_keys = ['name', 'age']
def __init__(self, **kwargs):
_dict = {}
# Set default values for listed keys
for item in self.listed_keys:
_dict[item] = 'default'
# Update the dictionary with all kwargs
_dict.update(kwargs)
# Have the keys of kwargs as instance attributes
self.__dict__.update(_dict)
未知または複数の引数を処理するためのもう1つの簡単な解決策は、次のとおりです。
class ExampleClass(object):
def __init__(self, x, y, **kwargs):
self.x = x
self.y = y
self.attributes = kwargs
def SomeFunction(self):
if 'something' in self.attributes:
dosomething()