#20 Pythonで学ぶ関数の応用の基本
前回の記事では、Pythonの関数の基本と「デフォルト引数」(引数に既定値を設定できる機能)に軽く触れました。今回はそこから一歩進んで、デフォルト引数の注意点と、引数の数を自由に増やせる「可変長引数」という仕組みを詳しく見ていきます。これを使えると、より柔軟で読みやすい関数が書けるようになります。
デフォルト引数のおさらいと落とし穴
デフォルト引数とは、関数を呼び出すときに値を省略した場合に使われる、あらかじめ決めておいた値のことです。
def greet(name="ゲスト", times=1):
for _ in range(times):
print(f"こんにちは、{name}さん")
greet() # こんにちは、ゲストさん(1回)
greet("太郎", 3) # こんにちは、太郎さん(3回)
ここで一つ、初心者がよくハマる注意点があります。デフォルト引数に「リスト」や「辞書」のような変更可能なデータ(専門用語で「ミュータブル」と呼びます)を指定すると、思わぬ不具合が起きることがあります。
def add_item(item, items=[]):
items.append(item)
return items
print(add_item("りんご")) # ['りんご']
print(add_item("みかん")) # ['りんご', 'みかん'] ← 前回の結果が残っている!
これは、デフォルト値の空リストが関数の定義時に一度だけ作られ、呼び出しのたびに使い回されるために起こります。対策として、デフォルト値にはNoneを指定し、関数の中で新しいリストを作るのが定番のやり方です。
def add_item(item, items=None):
if items is None:
items = []
items.append(item)
return items
可変長引数(*args)で引数の数を自由にする
「可変長引数」とは、呼び出し側が渡す引数の個数をあらかじめ決めずに済む仕組みのことです。引数名の前にアスタリスク(*)を1つ付けると、渡された複数の値がタプル(値を並べて保持するデータ型)としてまとめて受け取れます。
def total(*numbers):
return sum(numbers)
print(total(1, 2, 3)) # 6
print(total(10, 20, 30, 40)) # 100
慣例として引数名はargsとすることが多いですが、実際は好きな名前を使えます。大事なのはアスタリスクの数です。
キーワード引数もまとめて受け取る(**kwargs)
アスタリスクを2つ付けると、「名前=値」の形で渡された引数を辞書(キーと値のペアを保持するデータ型)としてまとめて受け取れます。
def show_profile(**info):
for key, value in info.items():
print(f"{key}: {value}")
show_profile(name="太郎", age=20, city="東京")
# name: 太郎
# age: 20
# city: 東京
*argsと**kwargsは同時に使うこともでき、その場合は「通常の引数 → *args → **kwargs」の順で書きます。
def order(item, *options, **details):
print(item, options, details)
order("コーヒー", "ホット", "Mサイズ", 砂糖=1, ミルク=True)
Pythonならではの書き方
JavaやC++のような言語では、引数の数や型が違う関数を複数用意する「オーバーロード」という手法がよく使われます。一方Pythonには、この意味でのオーバーロードの仕組みがありません。その代わりにデフォルト引数や*args・**kwargsを使い、1つの関数だけで柔軟に対応できるように書くのがPythonらしいスタイルです。関数を1つ書けば済むぶん、コードの見通しが良くなるという利点があります。
まとめ
デフォルト引数は呼び出し側の手間を減らしてくれますが、リストや辞書のような変更可能な値を既定値にすると不具合の原因になるため、Noneを使う書き方を覚えておきましょう。また*argsや**kwargsを使えば、引数の数が決まっていない場面でも柔軟に対応できる関数が書けます。どちらもPythonらしい書き方なので、ぜひ手元のエディタで動かしながら試してみてください。
関連記事
本ページはプロモーションを含みます。
参考書籍(PR)
Pythonをもっと学びたい方には「スッキリわかるPython入門 第2版」がおすすめです。
コメント
コメントを投稿