Pythonの関数定義には、少し特殊な記法がいくつかあります。
初めて見たときに戸惑いやすい「/
」「*
」「*args
」「**kwargs
」「デフォルト引数」などについて、学習中の自分用にまとめてみました。
1. /
(スラッシュ):位置専用引数
Python 3.8 以降では、関数定義で /
を使うことで「この引数は位置指定のみで渡してね」という制限をつけることができます。
使い方
def func(a, /):
print(a)
この関数は、以下のように位置でのみ引数を渡すことができます。
func(5) # OK
func(a=5) # エラーになる(TypeError)
意味と用途
- ライブラリやAPIの使用者に「この引数はキーワードで指定しないでね」と伝えるときに使います。
- 内部処理の高速化やインターフェースの固定にも使われます。
2. *
(アスタリスク):キーワード専用引数
関数定義における *
は、「ここから後ろの引数はキーワード指定必須ですよ」という意味になります。
使い方
def func(*, b):
print(b)
この関数は、以下のようにキーワード付きでのみ引数を渡すことができます。
func(b=10) # OK
func(10) # エラーになる(TypeError)
💡補足:/
と *
を組み合わせることもできる
たとえば以下のように書くと、aは位置専用、bはどちらでもOK、cはキーワード専用という指定ができます。
def sample(a, /, b, *, c):
print(a, b, c)
sample(1, 2, c=3) # OK
sample(a=1, b=2, c=3) # NG(aは位置専用)
3. 可変長引数:*args
と **kwargs
引数の数が決まっていないときに、まとめて受け取ることができます。
3.1 *args
:位置引数をまとめて受け取る
def func(*args):
print(args)
func(1, 2, 3) # 出力: (1, 2, 3)
引数はタプルとして args
にまとめられます。
3.2 **kwargs
:キーワード引数をまとめて受け取る
def func(**kwargs):
print(kwargs)
func(a=1, b=2) # 出力: {'a': 1, 'b': 2}
キーワード引数は辞書として kwargs
に渡されます。
🔍 補足:呼び出し側のアンパック記法
このように受け取った *args
や **kwargs
は、関数を呼び出す側でも「展開」して渡すことができます。
def func(a, b, c):
print(a, b, c)
args = (1, 2, 3)
func(*args) # → func(1, 2, 3)
kwargs = {"a": 1, "b": 2, "c": 3}
func(**kwargs) # → func(a=1, b=2, c=3)
4. デフォルト引数
4.1 デフォルト引数の基本
Pythonの関数では、引数にあらかじめ値を設定しておくことができます。これを「デフォルト引数(既定値)」と呼びます。
def greet(name="World"):
print(f"Hello, {name}!")
greet() # Hello, World!
greet("Alice") # Hello, Alice!
このように、引数を渡さなかった場合はデフォルト値が使われ、渡した場合はその値で上書きされます。
複数の引数がある場合は、デフォルト引数は必ず後ろに書く必要があります。
def add(a, b=10):
return a + b
def add(a=10, b): # ❌ エラー:デフォルト引数は後ろにまとめる必要がある
...
4.2 注意:ミュータブルなデフォルト引数は共有される
リストや辞書など、変更可能なオブジェクト(ミュータブルなオブジェクト)をデフォルト引数に使うと、関数定義時に1度だけ生成されて、それがずっと使い回されてしまうという仕様があります。
問題のある例
def append_item(item, lst=[]):
lst.append(item)
return lst
print(append_item(1)) # [1]
print(append_item(2)) # [1, 2] ← 2回目でも同じリストが使われてしまう!
安全な書き方(定型パターン)
def append_item(item, lst=None):
if lst is None:
lst = []
lst.append(item)
return lst
print(append_item(1)) # [1]
print(append_item(2)) # [2]
None
を使うことで、関数が呼ばれるたびに新しいリストを生成するようにできます。Pythonではこの書き方が“お作法”として広く使われています。
💡 補足
-
list
,dict
,set
などの ミュータブル型は共有されるため注意 -
int
,str
,tuple
などの イミュータブル型なら問題なし
おわりに
今回は関数定義時の少し特殊な記法について、自分なりに整理してまとめました。
特に /
や *
は初めて見ると意味が分かりにくいので、実際に動かして試してみると理解が進みました。
今後、関数を定義するときやライブラリの関数定義を読むときに活かせるようにしていきたいです。