こんにちは、かつコーチです。
これまでリスト・タプル・辞書・セットとデータ構造を解説してきました。
今回は、処理をひとまとまりにして再利用できる関数の定義方法を解説します。
関数とは、特定の処理をまとめて名前を付け、何度でも呼び出せるようにしたものです。
同じような処理を何度もコピペしていた私が、関数化の便利さに気づいてコードがぐっと読みやすくなった経験も踏まえて解説します。
この記事では、defでの基本的な関数定義から、デフォルト引数、可変長引数(*args・**kwargs)まで順を追って説明します。
基本の書き方:defでの関数定義
関数を定義する
関数はdef 関数名(引数):という形で定義します。
def greet(name):
return f"こんにちは、{name}さん"
message = greet("かつコーチ")
print(message)
# こんにちは、かつコーチさん
returnで返した値が、関数の戻り値になります。
returnを省略した場合、関数は自動的にNoneを返します。
def greet_no_return(name):
print(f"こんにちは、{name}さん")
result = greet_no_return("かつコーチ")
print(result)
# こんにちは、かつコーチさん
# None
デフォルト引数を設定する
引数に初期値を設定しておくと、呼び出し時に省略できるようになります。
def greet(name, honorific="さん"):
return f"こんにちは、{name}{honorific}"
print(greet("かつコーチ"))
# こんにちは、かつコーチさん
print(greet("かつコーチ", "先生"))
# こんにちは、かつコーチ先生
honorific="さん"と書くことで、第2引数を省略したときに自動で「さん」が使われます。
つまずきやすい設定・注意点:デフォルト引数の位置
デフォルト引数は、必ず通常の引数(デフォルト値なしの引数)より後ろに書く必要があります。
def greet(honorific="さん", name):
return f"こんにちは、{name}{honorific}"
SyntaxError: parameter without a default follows parameter with a default
引数の並び順は「デフォルト値なし → デフォルト値あり」の順が鉄則です。
よくあるつまずきポイント・エラー対処
デフォルト引数にミュータブルな値を使ってしまう
❌ Before:デフォルト引数にリストを直接指定する
私が初心者のころ、買い物リストに商品を追加する関数を、次のように書いていました。
def add_item(item, cart=[]):
cart.append(item)
return cart
print(add_item("りんご"))
# ['りんご']
print(add_item("バナナ"))
# ['りんご', 'バナナ']
「毎回空のリストが渡されて、新しいカートが作られるはず」と思っていましたが、2回目の呼び出しで前回の「りんご」が残ってしまい、原因が分からず困惑しました。
Pythonのデフォルト引数は、関数が定義されたタイミングで1度だけ生成され、以降の呼び出しでずっと使い回されるという仕様が原因でした。
✅ After:デフォルト引数にはNoneを使い、関数内で初期化する
この問題を避けるには、デフォルト引数にNoneを指定し、関数の内部で新しいリストを作成します。
def add_item(item, cart=None):
if cart is None:
cart = []
cart.append(item)
return cart
print(add_item("りんご"))
# ['りんご']
print(add_item("バナナ"))
# ['バナナ']
このように書けば、呼び出しごとに新しい空リストが作られ、意図した通りの動作になります。
リストや辞書など、変更可能な値をデフォルト引数に直接使わないというルールは、Pythonを書くうえで必ず覚えておくべき注意点です。
応用:可変長引数(*args・**kwargs)
引数の数が決まっていない関数を作りたい場合、*argsと**kwargsを使います。
*args:位置引数を可変長で受け取る
*argsを使うと、任意の個数の引数をタプルとして受け取れます。
def total(*args):
return sum(args)
print(total(1, 2, 3))
# 6
print(total(1, 2, 3, 4, 5))
# 15
**kwargs:キーワード引数を可変長で受け取る
**kwargsを使うと、任意の個数のキーワード引数を辞書として受け取れます。
def show_profile(**kwargs):
for key, value in kwargs.items():
print(f"{key}: {value}")
show_profile(name="かつコーチ", job="エンジニア", age=31)
# name: かつコーチ
# job: エンジニア
# age: 31
*argsと**kwargsは組み合わせて使うこともでき、この場合は「通常の引数 → *args → デフォルト引数 → **kwargs」の順で書きます。
def order(item, *sizes, discount=0, **options):
print(f"商品: {item}")
print(f"サイズ: {sizes}")
print(f"割引: {discount}%")
print(f"オプション: {options}")
order("Tシャツ", "S", "M", "L", discount=10, color="black", gift_wrap=True)
# 商品: Tシャツ
# サイズ: ('S', 'M', 'L')
# 割引: 10%
# オプション: {'color': 'black', 'gift_wrap': True}
APIのラッパー関数や、汎用性の高いユーティリティ関数を書くときに、この書き方はよく登場します。
まとめ
この記事のポイント
- 関数は
def 関数名(引数):で定義し、returnで値を返す - デフォルト引数は、通常の引数より後ろに書く必要がある
- デフォルト引数にリストなどのミュータブルな値を直接使うと、意図しない挙動になる
- 回避策として
Noneをデフォルトにし、関数内で初期化する *argsは可変長の位置引数、**kwargsは可変長のキーワード引数を受け取る
次に読むべき記事
関数の基本を押さえたら、次は変数の有効範囲を決める「スコープ」の考え方を学んでいきましょう。
→ 次の記事:スコープとグローバル変数・ローカル変数
タグ: Python, 初心者向け, 基本文法
