Python向けのテンプレートエンジンJinja
のコードリーディングをしていたところ、locals()
という見慣れない関数が使われていて、調べてみたのでメモしておきます。
locals()
とは?
リファレンスから抜粋すると、
現在のローカルシンボルテーブルを表す辞書を更新して返します。 関数ブロックで locals() を呼び出したときは自由変数が返されますが、クラスブロックでは返されません。 モジュールレベルでは、 locals() と globals() は同じ辞書であることに注意してください。
と、locals()
が実行された時点で定義されているローカル変数が返ってくると解釈しました。
試しにインタプリタを起動して、locals()
の挙動を確認してみます。
>>> a = 1
>>> def sample(b="2", c=True):
... d = 4
... l = locals()
... print(l)
... print(type(l))
...
>>> sample()
{'b': '2', 'c': True, 'd': 4}
<class 'dict'>
スコープ外であるa
は取得されず、sample
メソッド内で定義された変数が取得できたことから、リファレンスを読んだ解釈は齟齬なさそうに思います。
jinja
でのlocals()
使用箇所
jinja
にはインスタンスの設定情報を上書きするoverlay
メソッドが提供されています。
overlay
のメソッドを読んでいたところ、locals()
が以下のように使用されていました。
# https://github.com/pallets/jinja/blob/737a4cd41d09878e7e6c584a2062f5853dc30150/src/jinja2/environment.py#L385-L428
def overlay(
self,
block_start_string=missing,
# ... 省略 ...
bytecode_cache=missing,
):
# ... 省略 ...
args = dict(locals())
# ... 省略 ...
for key, value in iteritems(args):
if value is not missing:
setattr(rv, key, value)
overlay
の引数は多いのだが、locals()
を使ってargs
にまとめ、呼び出し側が指定した値のみを更新するよう、スマートな処理で実装されています。
上記から、locals()
は大量の引数を一つのdict
にまとめ、次の処理やjinja
のように呼び出し側から指定された値のみを取り出すような処理に向いていると感じました。
まとめ
以下、自分なりのまとめです。
-
locals()
は、locals()
実行時点までに定義されたローカル変数をdict
で取得できる - 大量の引数を
dict
にまとめて処理したいときに使える
以上になります。
書いた内容や解釈に間違い、他の使い道やバットノウハウ等ありましたら、コメントいただけると助かります。