時々、子モジュールに収めたい機能があるけどファイルは一つにしたいとか、同じモジュールファイル内に子のモジュールを作りたい時があるので、やってみました。
関数からモジュールを作る(デコレータ利用)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
import sys, types def module(func): """ 関数定義をモジュールに変換するデコレータ。 関数内での定義が、モジュールのコンテンツになります。 関数内の最後で、return locals() を書いてください。 """ modname = "%s.%s" % ( sys._getframe(1).f_locals["__name__"], func.__name__) mod = types.ModuleType(modname) setattr(mod, "__file__", __file__) for n, c in func().items(): setattr(mod, n, c) sys.modules[modname] = mod return mod @module def helper(): def bolder(text): return "<b>%s</b>" % text ... more difinition ... return locals() |
モジュール定義用の関数の中で、最後に return locals() ってのがイケていないですが、色々考えても回避できませんでした。orz…
クラスからモジュールを作る(メタクラス利用)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
import sys, types def modularize(name, bases, dct): """ クラス定義をモジュールに変換するメタクラス用関数。 クラス内での定義が、モジュールのコンテンツになります。 """ modname = "%s.%s" % ( sys._getframe(1).f_locals["__name__"], name) mod = types.ModuleType(modname) setattr(mod, "__file__", __file__) for n, c in dct.items(): setattr(mod, n, c) sys.modules[modname] = mod return mod class helper(object): __metaclass__ = modularize def bolder(text): return "<b>%s</b>" % text ... more difinition ... |
Python 3 なら、クラスデコレータを使えるでしょうかね。
なお、特にクラス定義を使いたい理由がなければ、上の関数定義を利用する方が、モジュールコンテンツのコーディング上便利だと思います。
定義したモジュールのインポート
例えば上述の定義を hoge モジュールに書いている場合、次のような感じで通常のモジュールのように呼び出せるようになります。
1 2 |
from hoge.helper import bolder from hoge.helper import * |
どうでしょうか?