はじめに
pythonの引数ですが、位置引数とキーワード引数、キーワードオンリー引数
*, **を使った複数引数の取得など混乱してきたので整理しました。
位置引数
関数名()の中にカンマ区切りで入れます。呼び出し側で渡された順に引数に渡されます。
def f(a, b):
return a, b
f(1, 2)
=======================
(1, 2)
引数を指定して代入する(キーワード引数)
a=1のように渡す引数をキーワード引数と呼びます。渡す順序が関係なくなります。
def f(a, b):
return a, b
f(b=2, a=1)
=======================
(1, 2)
キーワード引数の後に位置引数を渡すことは出来ません。
def f(a, b):
return a, b
f(b=2, 1)
=======================
SyntaxError: positional argument follows keyword argument
*, **を使って可変長の引数をtupleやdictとして受け取る
*を使うと可変長の引数がtupleとして渡せます。
def f(a, b, *c):
return a, b, c
f(1, 2, 3, 4)
=======================
(1, 2, (3, 4))
**を使うと可変長のキーワード引数がdictとして渡せます。
def f(a, b, **c):
return a, b, c
f(1, 2, x=3, y=4)
=======================
(1, 2, {'x': 3, 'y': 4})
*を使った引数の後に位置引数は代入できません。
def f(a, *b, c):
return a, b, c
f(1, 2, 3, 4)
=======================
TypeError: f() missing 1 required keyword-only argument: 'c'
**の後は位置引数もキーワード引数も代入出来ないようです。
def f(a, **b, c):
return a, b, c
f(1, x=2, y=3, c=4)
=======================
SyntaxError: invalid syntax
キーワードオンリー引数
Python3からキーワードオンリー引数が指定できるようになりました。
先頭に*つきの引数の後に来る引数は、キーワード引数としてのみ代入できます。
下記ですと、cは位置引数ではなくキーワード引数として代入する必要があります。
def f(a, *b, c):
return a, b, c
f(1, 2, 3, c=4)
=======================
(1, (2, 3), 4)
可変長の位置引数を使用しない場合は*単体で指定すると、それ以降の引数がキーワードオンリー引数になります。
def f(a, *, b):
return a, b
f(1, 2)
=======================
TypeError: f() takes 1 positional argument but 2 were given
def f(a, *, b):
return a, b
f(1, b=2)
=======================
(1, 2)
位置専用引数
コメントにて教えていただきましたが、位置専用引数もあるようです。
https://docs.python.org/ja/3/tutorial/controlflow.html#positional-only-parameters
def f(x, y):
print(x, y)
f(y=456, x=123)
============================
123 456
def f(x, y, /):
print(x, y)
f(y=456, x=123)
============================
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: f() got some positional-only arguments passed as keyword arguments: 'x, y'
f(x=123, y=456)
============================
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: f() got some positional-only arguments passed as keyword arguments: 'x, y'
f(123, 456)
============================
123 456
他の方から指摘を受けると、恥ずかしいのもあっていい勉強になるかもしれないと思った今日この頃。