PEP 562 — Module __getattr__ and __dir__を試してみた Part2

1pt   2018-07-12 03:03
IT技術情報局

前回の続き。

PEP 562 — Module __getattr__ and __dir__を試してみた – Qiita

「__getattr__と__dir__関数を試してみた」と言いながら、__dir__を試していないことに気づいた。

前回の続きでmain3.pyを追加して実行すると以下のようになる。

getattr/main3.py import getattr print(dir(getattr)) 実行結果 ['__all__', '__builtins__', '__cached__', '__doc__', '__file__', '__getattr__', '__loader__', '__name__', '__package__', '__path__', '__spec__', 'importlib']

ここには、file_loaderやdb_loaderが追加されていない。
そこで、__init__.pyに__dir__()を追加する。

__init__.py import importlib __all__ = ['file_loader', 'db_loader'] def __getattr__(name): if name in __all__: return importlib.import_module("." + name, __name__) raise AttributeError(f"module {__name__!r} has no attribute {name!r}") def __dir__(): return __all__ 実行結果 ['db_loader', 'file_loader']

ただし、これだと__all__に代入した2つしか出力されなくなるので、

__init__.py import importlib import sys __all__ = ['file_loader', 'db_loader'] def __getattr__(name): if name in __all__: return importlib.import_module("." + name, __name__) raise AttributeError(f"module {__name__!r} has no attribute {name!r}") # 位置が重要 __all__ += dir(sys.modules[__name__]) def __dir__(): return __all__ 実行結果 ['__all__', '__builtins__', '__cached__', '__doc__', '__file__', '__getattr__', '__loader__', '__name__', '__package__', '__path__', '__spec__', 'db_loader', 'file_loader', 'importlib', 'sys']

こうすることで、元のアトリビュートに追加することができる。
注:__dir__()の中でdir()を呼ぶと無限再起してしまいます

ちなみに、あまり考えずにgetattrディレクトリを作ってパッケージ名にしてしまったけど、getattr()組み込み関数があるのでよくない命名だった。

Source: python tag

   ITアンテナトップページへ
情報処理/ITの話題が沢山。