Pythonにおいて、関数は「第一級オブジェクト(First-Class Object)」として扱われます。これは、関数が数値や文字列などの他のデータ型と同じように、変数に代入したり、他の関数の引数として渡したり、リストや辞書の中に格納したりできることを意味します。
この性質を理解すると、柔軟で再利用性の高いコードを設計できるようになります。
この記事では、関数を変数として扱う基本的な方法と、その応用例について解説します。
1. 関数を変数に代入する
関数を定義した後、その関数名(括弧を付けない状態)は「関数オブジェクトそのもの」を指します。これを別の変数に代入することで、その変数を通じて関数を呼び出すことが可能になります。
具体的なコード例
文字列を大文字に変換して装飾する関数を定義し、それを別の変数に代入して利用する例です。
def format_title(text):
"""テキストを大文字にして装飾する関数"""
return f"*** {text.upper()} ***"
# 関数そのものを変数 'processor' に代入
# 注意: format_title() ではなく format_title と記述する
processor = format_title
# 変数経由で関数を実行
result = processor("python programming")
print(result)
# 変数 processor がどの関数を参照しているか確認
print(f"参照先: {processor}")
実行結果:
*** PYTHON PROGRAMMING ***
参照先: <function format_title at 0x...>
processor という変数が format_title 関数と同じ振る舞いをしていることがわかります。
重要な区別:括弧の有無
format_title: 関数オブジェクトそのもの。変数に代入できる。format_title("..."): 関数の実行結果(戻り値)。
代入する際は、括弧を付けないように注意する必要があります。
2. 関数を引数として渡す(高階関数)
関数を変数として扱えるため、他の関数の引数として「処理そのもの」を渡すことができます。このように関数を受け取ったり返したりする関数を「高階関数」と呼びます。
これにより、処理の一部を外部から注入(Dependency Injection)するような設計が可能になります。
具体的なコード例
数値のリストと「変換処理を行う関数」を受け取り、リストの全要素を変換して返す関数を作成します。
def process_list(data_list, converter_func):
"""
リストの各要素に対して、渡された関数(converter_func)を適用する
"""
result_list = []
for item in data_list:
# 引数として渡された関数を実行
converted_item = converter_func(item)
result_list.append(converted_item)
return result_list
# 利用する関数1:2倍にする
def double_value(x):
return x * 2
# 利用する関数2:文字列にする
def to_string_format(x):
return f"Value: {x}"
numbers = [10, 20, 30]
# 1. 2倍にする関数を渡す
doubled = process_list(numbers, double_value)
print(f"2倍: {doubled}")
# 2. 文字列化する関数を渡す
formatted = process_list(numbers, to_string_format)
print(f"整形: {formatted}")
実行結果:
2倍: [20, 40, 60]
整形: ['Value: 10', 'Value: 20', 'Value: 30']
process_list 関数の中身を変更することなく、渡す関数を変えるだけで処理内容を切り替えることができました。
3. リストや辞書に関数を格納する
関数はオブジェクトであるため、リストや辞書の要素としても扱えます。
特に辞書を使った方法は、条件分岐(if-elif-else)の代わりとして、入力に応じた処理を切り替える「ディスパッチテーブル」の実装によく使われます。
具体的なコード例
計算の種類(文字列)に応じて、実行する関数を切り替えるプログラムです。
def add(x, y):
return x + y
def subtract(x, y):
return x - y
def multiply(x, y):
return x * y
# 関数を辞書に登録する(コマンド名: 関数オブジェクト)
operations = {
"plus": add,
"minus": subtract,
"multi": multiply
}
def execute_calculation(command, a, b):
# 辞書から関数を取得
# 存在しないコマンドの場合は None を返す
func = operations.get(command)
if func:
return func(a, b)
else:
return "無効なコマンドです"
# 実行
print(f"足し算: {execute_calculation('plus', 10, 5)}")
print(f"掛け算: {execute_calculation('multi', 10, 5)}")
print(f"エラー: {execute_calculation('divide', 10, 5)}")
実行結果:
足し算: 15
掛け算: 50
エラー: 無効なコマンドです
この方法を使うと、機能を追加する際に execute_calculation 関数内の if 文を増やす必要がなく、単に operations 辞書に関数を追加するだけで済みます。
まとめ
- Pythonの関数は第一級オブジェクトであり、変数への代入が可能です。
- 関数名に括弧を付けずに記述することで、実行せずにオブジェクトとして扱えます。
- 他の関数に引数として渡したり、辞書に格納して管理したりすることで、柔軟で拡張性の高いプログラムを作成できます。
