🪆
関数の中の関数について【超初心者向けの記事】「ネストされた関数」「入れ子の関数」「ローカル関数」とも言う
さて今回は、JavaScriptやPythonで一般的に用いられる
「ネストされた関数」(「入れ子の関数」、「ローカル関数」)についてです。
C言語を中心にやっていた元組み込み系エンジニアは
この記述がはじめサッパリわからなかったのでまとめてみました。
(C言語ではネストされた関数の記述は不可能のようです)
「ネストされた関数」のメリット
JavaScriptやPythonで「ネストされた関数」を使う主なメリットは
- スコープを制限できる
- クロージャの活用(外側の変数を使える)
というのがあります。
JavaScriptの例
スコープの制限
document.addEventListener('DOMContentLoaded', function() {
const modal = document.getElementById('eventModal');
// この関数はこのスコープでしか使えない
function closeModal() {
modal.style.display = 'none';
}
// closeModalはこの中でしか使えないので、
// 他のコードから誤って呼び出されることがない
window.onclick = function(event) {
if (event.target == modal) {
closeModal();
}
}
});
クロージャの活用(外側の変数を使える)
function createCounter() {
let count = 0; // 外側の変数
// この関数は外側のcountを使える
function increment() {
count++;
console.log(count);
}
return increment;
}
const counter = createCounter();
counter(); // 1
counter(); // 2
この機能により
- コードの整理がしやすくなる
- 変数のスコープを制限できる
- 関連する処理をまとめやすくなる
といった利点があります。
Pythonの例
スコープの制限
def process_order():
items = get_items()
# この関数はprocess_order内でしか使えない
def calculate_tax(price):
return price * 0.1
total = 0
for item in items:
tax = calculate_tax(item.price)
total += item.price + tax
return total
クロージャの活用
def create_counter():
count = 0
def increment():
nonlocal count # Pythonでは外側の変数を変更する場合nonlocalが必要
count += 1
print(count)
return increment
counter = create_counter()
counter() # 1
counter() # 2
ただし、小さな違いもあります。
- Pythonでは外側の変数を変更する場合、
nonlocal
宣言が必要 - JavaScriptでは
var
,let
,const
でスコープが変わりますが、Pythonではそういった違いはない - Pythonではデコレータを作る際にネストされた関数がよく使われる(これはJavaScriptにはない使い方)
デコレータとは?
デコレータは、関数やクラスの動作を変更したり拡張したりするためのPythonの機能です。
簡単な例を見てみましょう
def print_function_name(func):
def wrapper():
print(f"関数名: {func.__name__}が実行されます")
func() # 元の関数を実行
print("関数の実行が終わりました")
return wrapper
# デコレータを使用
@print_function_name
def hello():
print("Hello!")
# hello()を実行すると...
hello()
このコードを実行すると
関数名: helloが実行されます
Hello!
関数の実行が終わりました
が出力されます。
Djangoでは、よく使われるデコレータの例として:
from django.contrib.auth.decorators import login_required
@login_required
def my_view(request):
# このビューはログインしているユーザーだけがアクセスできる
return render(request, 'my_template.html')
このように、@login_required
をつけることで、そのビューにアクセスするには事前にログインが必要になります。
デコレータを使うメリットは
- コードの再利用が簡単
- 既存の関数の動作を変更せずに、新しい機能を追加できる
- コードがきれいで読みやすくなる
ということがあります。
おしまいに
- C++: ラムダ式で似た機能を実現
- C#: 可能だが一般的ではない
ということですが、「ネストされた関数」をソースで見かけたことが無かったので
今回のJavaScriptやPythonの記述については学びになりました。
基礎中の基礎かもしれず、
「そんなことも知らんのか」という声が飛んできそうですが、
「まだまだ伸びしろがある」と謎にポジティブに考えて
4月からのWeb系開発現場への転職に備えたいと思います(大丈夫か)
Discussion