グローバル変数は必要です
Life is beautiful: Python Hack : 噛めば噛むほどおいしくなるクロージャの話クロージャと無名関数を使うと、こんな風に実装することができる。
import yaml def _get_from_disk(): data = open('config.yaml').read().decode('utf8') config = yaml.load(data) # クロージャ内に隠蔽・保持されるローカル変数 global get get = lambda : config # 二回目からはconfigを返す無名関数を呼ぶ様に変更 return get() get = _get_from_disk # 初回のみローダーを実行
いやいや、それはいけません!
このコードは、config.py というモジュールの一部で、
import config #config.get()を使って処理
という使い方を想定していますが、こういう使い方も出来てしまいます。
from config import get as config_get #get()を使って処理
こうすると、config_getの参照先は、config.pyの中でどんな処理をしようと、_get_from_diskのままなので、config_getを呼び出すと毎回ファイルを読み込むことになってしまいます。
同じ問題は、メソッドでも発生します。メソッドオブジェクトを変数に代入した場合です。たとえば、
#!python3
# -*- coding: cp932 -*-
class Config:
def get(self):
self.get = lambda : 1 #2回目以降は1を返すつもり
return 0 # 初回のみ0を返すつもり
c = Config()
get = c.get #メソッドを変数に代入
print(c.get()) # => 0
print(c.get()) # => 1
print(get()) # => 0
というわけで、「初回のみ〜する」場合は、諦めてグローバル変数やメンバ変数を使いましょう。