ProgrammingPython開発者

Pythonの関数における*argsと**kwargsの動作を説明してください。どのように使用され、誤った使用による危険性は何ですか?また、通常の引数および名前付き引数とどのように正しく組み合わせることができますか?

Hintsage AIアシスタントで面接を突破

回答

*argsは、任意の数の位置引数をタプルとして集約します。

**kwargsは、任意の数の名前付き引数(キー=値)を辞書として集約します。

これにより、柔軟なインターフェースを持つ関数を記述できます:

def my_func(a, b, *args, **kwargs): print(a, b) print(args) print(kwargs) my_func(1, 2, 3, 4, x=10, y=20) # 1 2 # (3, 4) # {'x': 10, 'y': 20}

注意点:

  • 通常の引数は最初に配置され、次に*args、その後にデフォルト値を持つ名前付き引数が続き、最後に**kwargsがくるという順序で関数を定義しなければなりません。
  • 関数を呼び出す際に、*を使用してシーケンスを「アンパック」し、**を使用して辞書を「アンパック」できます。
  • 同じパラメータを再度定義することはできず、TypeErrorが発生します。

トリッキーな質問

デフォルト値のある名前付き引数と*argsの順序を変更できますか?例えば:

def foo(a, *args, x=10, **kwargs): pass

それとも常に*argsの後にデフォルト値を配置する必要がありますか?

答え:

Python 3では可能です!次のように(Python 2では動作しませんでした):

def foo(a, *args, x=10): pass

*argsの後のパラメータ(「キーワード専用引数」)は、デフォルト値を持つか必須であることができ、名前でのみ指定できます。

このテーマに関する実際のエラーの例


ストーリー

**不正確な引数を*args/kwargs経由で渡す

REST APIサービスでは、データのマーシャリング自動化が**kwargsを通じて構築されました。余分なパラメータが見逃され、関数がkwargsに予期しない値を受け取り、制御ロジックが失われ、デバッグが難しいバグが発生しました。


ストーリー

名前付き引数の重複

関数呼び出しにおいて、開発者はパラメータを明示的に指定し、さらに**kwargsを通じて指定してしまいました。例えば:my_func(a=1, **{"a": 2})。結果として、TypeErrorが発生し、サービスがクラッシュしました。


ストーリー

位置引数または名前付き引数だけを忘れる

デコレーターを作成する際に、パラメータの誤った渡し方(順序と構造が守られていない)により、元の関数が合意の変更により期待される引数の数を受け取らず、プロダクションでTypeError呼び出しのエラーが発生し始めました。