関数の基本と意義
関数は処理をまとまりとして切り出し再利用するための仕組みです。
def キーワードで定義し、引数と戻り値を通じてデータの受け渡しを行います。
関数を使って処理を分割すると、可読性と保守性が向上します。簡潔で単一責任の関数を心がけてください。
# 関数の例 def greet(name): """名前を受け取り挨拶を表示する関数。""" print(f"Hello, {name}") greet("Alice")
引数の扱いと返り値
位置引数とキーワード引数、デフォルト引数、可変長引数(*args, **kwargs)はそれぞれ役割が異なります。デフォルト引数をミュータブルなオブジェクトで設定すると予期せぬ動作を招くことがあるため注意してください。
戻り値は必ず明示すると呼び出し側が扱いやすくなります。
# 引数の例 def add(a, b=0, *args, **kwargs): total = a + b for v in args: total += v return total
スコープと名前空間の注意
関数内で定義した変数はローカルスコープに属します。
グローバル変数を関数内で変更する必要がある場合は global 宣言で明示できますが、設計上は避けるのが望ましいです。
ネストした関数やクロージャを使う際は名前解決ルール(LEGB)を理解しておくとトラブルを避けられます。
# スコープの例 x = 10 def func(): x = 5 # ローカル print(x) func() # 5 print(x) # 10
無名関数(lambda)と高階関数
lambda は短い無名関数をその場で定義するための式です。
map, filter, sorted のキー関数など、使いどころは限られます。
可読性を損なう場合は通常の def を選ぶ方が良いでしょう。
# lambda の例 squares = list(map(lambda x: x*x, range(5)))
ドキュメンテーション文字列(docstring)
関数の先頭に三重引用符で説明を書くと、help() などから参照できます。
引数と戻り値の型や意味、例外条件を簡潔に記載すると利用者に親切です。
プロジェクト全体で docstring のスタイルを統一するとドキュメント生成ツールとの相性が良くなります。
def multiply(a, b): """2つの数値を掛け合わせて返す関数。 引数: a (int|float): 被乗数。 b (int|float): 乗数。 戻り値: int|float: 積。 """ return a * b
モジュール化とパッケージ設計
1つの .py ファイルがモジュールであり、関連するモジュールを階層的にまとめたものがパッケージです。
機能ごとにモジュールを分割し、明確な公開 API を提供することで再利用性が高まります。
__init__.py はパッケージの初期化処理や公開シンボルの制御に使いますが、無理に多機能にする必要はありません。
# パッケージからのインポート例 from mypackage.mymodule import myfunction
外部パッケージの管理
外部ライブラリは pip でインストールしますが、プロジェクトごとに仮想環境を使い依存を分離することが重要です。
requirements.txt や poetry のようなツールで依存管理を行うと、再現性の高い開発環境が維持できます。
# pip の基本 pip install requests
実務的なベストプラクティス
関数は単一責任に保ち、テスト可能な小さな単位で設計してください。
副作用を持つ処理は明確にし、戻り値で状態を返すなど扱いやすくすることがポイントです。
モジュール設計では依存性を明確にし、循環依存を避けることがメンテナンス性向上に繋がります。
項目 | 補足 |
---|---|
def / lambda | 用途に応じて使い分ける。可読性を優先。 |
import | 必要最小限を明示的にインポートする方が読みやすい。 |