7

これらの異なる動作を考慮してください::

>> def minus(a, b):
>>    return a - b

>> minus(**dict(b=2, a=1))
-1

>> int(**dict(base=2, x='100'))
4

>> import operator
>> operator.sub.__doc__
'sub(a, b) -- Same as a - b.'
>> operator.sub(**dict(b=2, a=1))
TypeError: sub() takes no keyword arguments

operator.subが と異なる動作をするのはなぜint(x, [base])ですか?

4

3 に答える 3

7

実装の詳細です。引数を取得する Python C API は、位置引数とキーワード引数を分離します。位置引数には、内部的に名前さえありません。

operator.add関数 (および のような同様のもの)の引数を取得するために使用されるコードsubは次のとおりです。

PyArg_UnpackTuple(a,#OP,2,2,&a1,&a2)

ご覧のとおり、引数名は含まれていません。関連するコード全体operator.addは次のとおりです。

#define spam2(OP,AOP) static PyObject *OP(PyObject *s, PyObject *a) { \
  PyObject *a1, *a2; \
  if(! PyArg_UnpackTuple(a,#OP,2,2,&a1,&a2)) return NULL; \
  return AOP(a1,a2); }

spam2(op_add           , PyNumber_Add)
#define spam2(OP,ALTOP,DOC) {#OP, op_##OP, METH_VARARGS, PyDoc_STR(DOC)}, \
                           {#ALTOP, op_##OP, METH_VARARGS, PyDoc_STR(DOC)},
spam2(add,__add__, "add(a, b) -- Same as a + b.")

ご覧のとおり、abが使用されている場所は docstring だけです。METH_KEYWORDSメソッド定義は、メソッドがキーワード引数を受け入れるために必要なフラグも使用しません。

一般的に言えば、引数名がわかっているpythonベースの関数は常にキーワード引数を受け入れると安全に想定できます(もちろん、誰かが解凍して厄介なことをすることができます*argsが、引数が正常に見える関数ドキュメントを作成できます).キーワード引数を受け入れない場合があります。いくつかの引数またはオプションの引数を持つ関数が、後の/オプションの引数のキーワード引数を受け入れる可能性は十分にあります。しかし、あなたはほとんどそれをテストする必要があります.

python-ideas メーリングリストのあらゆる場所で、キーワード引数のサポートに関する議論を見つけることができます。また、 Guido van Rossum (慈悲深い終身独裁者、別名 Python の作成者)の声明もあります。

うーん。ord(char=x) の例が示すように、多くの (ほとんどの?) 1-arg 関数と選択された 2-arg 関数 (およびめったに 3+-arg 関数) では、これにより読みやすさが低下すると思います。

私は実際には、引数をキーワード引数として指定できないことを示す構文上の機能を見たいと思っています (キーワードでなければならないことを示す構文を既に追加したように)。

キーワード引数の追加が完全に間違っていると私が思う領域の 1 つは、組み込み型または ABC のメソッドであり、オーバーライド可能であることです。たとえば、dict の pop() メソッドを考えてみましょう。引数名は現在文書化されていないため、誰かが dict をサブクラス化してこのメ​​ソッドをオーバーライドした場合、またはダックタイピングを使用して dict をエミュレートしようとする別の可変マッピング クラスを作成した場合、引数名が何であるかは問題ではありません -- すべての呼び出し元 ( dict、dict サブクラス、または dict のようなアヒルを期待する) は、呼び出しで位置引数を使用します。しかし、pop() の引数名を文書化して、ユーザーがこれらを使い始めると、ほとんどの dict サブクラスとダックが突然壊れてしまいます (偶然にも同じ名前を選んだ場合を除く)。

于 2012-06-05T08:48:35.717 に答える
4

operator関数を異なる方法で定義する C モジュールです。モジュール初期化の関数宣言に が含まれていない限り、関数はMETH_KEYWORDSどのような条件下でもキーワード引数を受け入れず、質問に示されているエラーが発生します。

于 2012-06-05T08:50:18.643 に答える
3

minus(**dict(b=2, a=1))に展開しminus(b=2, a=1)ます。これは、定義に引数名aとがあるため機能しますb

operator.sub(**dict(b=2, a=1))に展開しoperator.sub(b=2, a=1)ます。sub はキーワード引数を受け入れないため、これは機能しません。

于 2012-06-05T08:45:56.047 に答える