web-dev-qa-db-ja.com

キーワードのみの引数を使用する安全な方法は何ですか?

キーワードのみの引数 は、キーワードによってのみ関数に提供できる引数です。 Pythonでは、関数のシグネチャ内の単一のアスタリスクで定義されています。次に例を示します。

>>> def foo(bar, *, baz):
        print(bar, baz)
>>> foo(1, baz=2)
    1 2
>>> foo(1, 2)
TypeError: foo() takes 1 positional argument but 2 were given

それらを使用することには、文体上の長所と短所だけでなく、機能性もあります。ここに私が知っているいくつかがあります:

利点:

そして欠点:

  • すべての引数をキーワードのみにすると、 map で関数を使用できなくなります。例えば:

    >>> def square(*, x):
            return x * 2
    
    >>> list(map(square, [1, 2, 3]))
    TypeError: square() takes 0 positional arguments but 1 was given
    

PEP 3102 でキーワードのみの引数を適切に使用する方法に関する一般的な説明が見つからなかったので、そもそもそれを他のソースで提案しました。

したがって、私の質問は次のとおりです。キーワードのみの引数を使用するときに、私が知らない他の落とし穴はありますか?将来的に何かを壊すことなく、どのように安全に使用できますか?

3
Georgy

実際、言語機能には落とし穴、コスト、および利点があります。プログラミング言語スタイルガイド( Google Style Guides など)や JavaScript:The Good Parts などのコアポイントは、驚くべき、エラーが発生しやすい、トリッキーな機能や使用を避けることです、または維持するのが難しい。

キーワードのみの引数の良い例をいくつか示します。

  • 呼び出しサイトで明白でないオプション、特に。ブールフラグと複数のオプション。 io.open() の場合、fileおよびmodeの後のすべての引数をキーワードのみにすることは妥当です(後方互換性を除く)。
    io.open(file, 'r', 0, None, '', '', False)
  • まっすぐに続けるのが難しい引数:
    def address(*, country, administrative_area, sub_administrative_area, locality, dependent_locality, postal_code, thoroughfare, premise)
  • 呼び出し元に明示的に渡すことを要求する引数:
    def delete(base, *, recursive)
  • 可変引数も取る関数のオプション:
    def send(topic, message, *values, debug=True)
  • 将来的に可変引数を取る可能性のある関数のオプション。これは間違いなく判断の呼びかけです。ポイントは、varargsパラメーターを追加すると、位置パラメーターとしてオプションを渡すすべての呼び出し元が壊れることです。オプションをキーワードのみのパラメーターとして定義すると、varagsパラメーターを追加する機能が予約されます。
    def send(topic, message, *, debug=True)

キーワードのみの引数を使用しないいくつかのケースを以下に示します。

  • Python 2.との互換性が必要なコード。
  • 一般的な関数型プログラミング:map()filter()apply()、...
  • 引数が1つの関数:repr(object)
  • 可変引数:max(x, y, z, t)
  • キーワードのみの引数を使用すると、冗長性と煩雑さが増し、利点がなくなります:bitwise_and(x1, x2)。 [numpy.bitwise_and()は、これらの2つの引数と、互換性を除いてキーワードのみの公平なゲームである一連のオプションの引数を取ります。]

キーワードのみの引数のその他のいくつかの落とし穴:

  • これは、新しいチームメンバーがPythonとコードベースをすぐに理解できるようになる時期を知るためのもう1つの機能です。
  • 関数定義の余分な複雑さと注意散漫。 (あれは何でしょう *?)
  • 一部の開発ツールではうまく処理できない場合があります。構文ハイライター、差分ツール、リファクタリングエディター、コードインスペクター、C相互運用機能、RPC(リモートプロシージャコール)コードジェネレーターなど。
  • 言語機能は、驚くべき方法で相互に対話できます。 「追加するものが何もないときではなく、取り除くものが残っていないときに、完璧が達成されます。」 -アントワーヌドサンテグジュペリ。
5
Jerry101

キーワードのみの引数は単なるtoolであり、すべての1つの完璧なツールはありませんmapのように機能しない場合は、位置引数を使用します。

キーワードのみの引数を安全に使用できます。コードの変更、リファクタリングは、futureを心配する一般的な方法です。将来を予測する代わりに、過去を現在のニーズに適応させます。

キーワードのみの引数のベストプラクティスは、個人設定とソフトウェアデザインの回答です。

インターネット検索からのランダムな結果:4関数の引数のベストプラクティスhttp://www.informit.com/articles/article.aspx? p = 2314818

2
dario

キーワードのみの引数を使用することに特別な欠点はありません。

確かに、あなたの関数は位置引数を持つものとは異なるシグネチャを持つため、特定のシグネチャに一致する関数が渡されることを期待する他の関数では機能しません。

しかし、これは署名の互換性のない変更にも当てはまり、関数をラップすることで簡単に回避できます。

この場合、引数を検査して最初のキーワード引数を使用するマップ関数も作成することができます。

単一の引数を持つ関数がキーワードの使用を強制するのは無意味であり、エラーをスローすることは、この動作を実装するのと同じくらい意味があると私は主張しますが。

1
Ewan