** kwargsで** kwargs引数を別の関数に渡す


152

次の例は理解できません。これらの機能があるとしましょう。

# python likes
def save(filename, data, **kwargs):
    fo = openX(filename, "w", **kwargs) # <- #1
    fo.write(data)
    fo.close()
# python doesnt like
def save2(filename, data, **kwargs):
    fo = openX(filename, "w", kwargs) # <- #2
    fo.write(data)
    fo.close()

def openX(filename, mode, **kwargs):
    #doing something fancy and returning a file object

なぜ#1が正しいソリューションで、#2が間違っているのですか?**kwargs基本的にはdictなので、openXに引数を渡したい場合、正しい方法は**dictを付けずに与えるだけだと思います。しかし、pythonは明らかに2番目の引数が気に入らず、引数を2つではなく3つ指定したことを教えてくれます。これの背後にある理由は何ですか?

python 

5
なぜ**argsコードでそれを呼び出すのかしら。これは、人々が混同する可能性があるため、おそらく最悪の名前になる可能性があります*args
John La Rooy

1
* argsを実際に使用することはないので、** args ^^を使用しますが、変更することもできます。

回答:


155

2番目の例では、ファイル名、モード、辞書(kwargs)の3つの引数を指定します。しかし、Pythonは次のことを期待しています。2つの仮引数とキーワード引数。

辞書の前に「**」を付けることにより、kwargsキーワード引数に辞書を解凍します。

辞書(type dict)は、キーと値のペアを含む単一の変数です。

「キーワード引数」は、キーと値のメソッドパラメータです。

**関数呼び出し中にプレフィックスを付けることにより、任意の辞書をキーワード引数にアンパックできます。


5
今私はそれを手に入れました。キーワードと口述は同じものだと思いました。

13
「すべての辞書は、関数呼び出し中に**を前に付けることにより、キーワードに展開できます。<-それはかっこいい


8
実際のコード例では、この答えがかなり明確になります。
OrangeDog 2017

12

**構文は、辞書にキーワード引数を収集するためのPythonを伝えます。save2非キーワード引数(辞書オブジェクト)としてそれを渡しています。openXので、任意のキーワード引数を見ていない**args使用されません。代わりに、3番目の非キーワード引数(辞書)を取得しています。これを修正するには、openX関数の定義を変更します。

def openX(filename, mode, kwargs):
    pass

ありがとう、でも保存せずにopenXを使いたいので、キーワードにこだわる必要があります。キーワードを渡すことは基本的には

@xMRWディクショナリをパラメーターとして任意の関数に渡すことができるため、同じことはできません。その時あなたの#1は正しいものです。
キース

8

@geccoの答えを拡張して、以下は違いを示す例です:

def foo(**kwargs):
    for entry in kwargs.items():
        print("Key: {}, value: {}".format(entry[0], entry[1]))

# call using normal keys:
foo(a=1, b=2, c=3)
# call using an unpacked dictionary:
foo(**{"a": 1, "b":2, "c":3})

# call using a dictionary fails because the function will think you are
# giving it a positional argument
foo({"a": 1, "b": 2, "c": 3})
# this yields the same error as any other positional argument
foo(3)
foo("string")

ここでは、ディクショナリーの解凍の仕組みと、実際のディクショナリーの送信が失敗する理由を確認できます。


1

辞書は単一の値だからです。キーワード引数のグループとして渡す場合は、キーワード展開を使用する必要があります。


申し訳ありませんが、「キーワード拡張」とは何ですか。** argsの代わりにdict_varを使用し、def func(argument、dict_var = 0)... func(1、{1: "a"、2: "b"})を使用する必要があるということですか

1

#2の場合、argsはdict値を持つ仮パラメーターのみであり、キーワードタイプパラメーターではありません。

キーワード型パラメーターをキーワード引数に渡したい場合辞書の前に**を指定する必要があります。つまり、** args

** kwの使用の詳細については、こちらをご覧ください。

http://www.saltycrane.com/blog/2008/01/how-to-use-args-and-kwargs-in-python/


** kwargsとdictの間には大きな違いがありますか?

ありがとう、私はいつもわからないトピックについてもっと読みたいです。
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.