2015年12月27日

lazy import 3

lazy import の可読性を向上させるテクニックを紹介します。


こちらで lazy import を紹介しました。実装例を再掲します。

def cat(filename):
    if filename.startswith('http://'):
        import urllib.request  # ここでimport
        print(urllib.request.urlopen(filename).read())
    else:
        print(open(filename).read())
lazy import によりプログラムの起動が速くなるのは利点ですが、一方で以下のような欠点もあります。
  • 冒頭に import が無いので、他モジュールへの依存関係を把握しづらい
  • 対象のモジュールを複数箇所で使用している場合、使用する度に import を書く必要がある

lazy import 専用のクラスを定義することで、上記の欠点を解消することができます。
以下にクラスの定義と使い方を記します。
# lazy import用クラス
class LazyImport(object):
    def __init__(self, name):
        self.__name = name
        self.__module = None

    def __getattr__(self, attr):
        # 初回のみimportする
        if self.__module is None:
            self.__module = __import__(self.__name)
        return getattr(self.__module, attr)

# 冒頭でimportと似た書式
urllib_request = LazyImport('urllib.request')

def cat(filename):
    if filename.startswith('http://'):
        # ここでimportを書かなくてよい
        print(urllib_request.urlopen(filename).read())
    else:
        print(open(filename).read())

LazyImportクラスを利用することで、先に挙げた2つの欠点がいずれも解消されました。
ただし、このクラスは参照の度に getattr() を呼ぶため、呼び出し速度は速くありません。

0 件のコメント:

コメントを投稿