dir(cls)は何をしているんだ
Luigiという公式に某配管工の弟なフロー制御フレームワークの実装を読む日々。つらみ。
そもそもLuigiとはなんぞや?の場合、以下を読むとなんとなくイメージつくかもです。 https://qiita.com/colspan/items/453aeec7f4f420b91241qiita.com
読んでいくときにこれ何やってるんだろ?と思うことしかないんだが、 1点、dir(cls)はなにやってるんだ?ってところを調べたのでメモしておく。
端的に言うと、dir(cls)で対象モジュール内の変数とか関数とかの名前(メンバ)を返すことができる。
指定したモジュールやクラス、インスタンスなどの名前空間の名前一覧を返す関数である。
もし引数を省略した場合は現在のスコープの名前一覧を返す。
これを使用すれば、モジュールに含まれたクラスの名前や、クラス内のメンバの名前を調べることができる。
魔術師見習いのノート
上記サイトの例だと
import sys dir(sys)
['__displayhook__', '__doc__', '__excepthook__', '__interactivehook__', '__loader__', '__name__', '__package__', '__spec__', '__stderr__', '__stdin__', '__stdout__', '_clear_type_cache', '_current_frames', '_debugmallocstats', '_getframe', '_home', '_mercurial', '_xoptions', 'api_version', 'argv', 'base_exec_prefix', 'base_prefix', 'builtin_module_names', 'byteorder', 'call_tracing', 'callstats', 'copyright', 'displayhook', 'dllhandle', 'dont_write_bytecode', 'exc_info', 'excepthook', 'exec_prefix', 'executable', 'exit', 'flags', 'float_info', 'float_repr_style', 'get_coroutine_wrapper', 'getallocatedblocks', 'getcheckinterval', 'getdefaultencoding', 'getfilesystemencoding', 'getprofile', 'getrecursionlimit', 'getrefcount', 'getsizeof', 'getswitchinterval', 'gettrace', 'getwindowsversion', 'hash_info', 'hexversion', 'implementation', 'int_info', 'intern', 'is_finalizing', 'last_traceback', 'last_type', 'last_value', 'maxsize', 'maxunicode', 'meta_path', 'modules', 'path', 'path_hooks', 'path_importer_cache', 'platform', 'prefix', 'ps1', 'ps2', 'ps3', 'set_coroutine_wrapper', 'setcheckinterval', 'setprofile', 'setrecursionlimit', 'setswitchinterval', 'settrace', 'stderr', 'stdin', 'stdout', 'thread_info', 'version', 'version_info', 'warnoptions', 'winver']
こんな感じでsysの中に存在している名前を見ることができる。
でもって、Luigiの中の該当処理はっていうと、
task.py
from luigi import parameter from luigi.task_register import Register ・ ・ ・ Parameter = parameter.Parameter @classmethod def get_params(cls): """ Returns all of the Parameters for this Task. """ # We want to do this here and not at class instantiation, or else there is no room to extend classes dynamically params = [] for param_name in dir(cls): param_obj = getattr(cls, param_name) if not isinstance(param_obj, Parameter): continue params.append((param_name, param_obj)) # The order the parameters are created matters. See Parameter class params.sort(key=lambda t: t[1]._counter) return params
for param_name in dir(cls):
でcls内のメンバ分ループを実行する。
param_obj = getattr(cls, param_name)
でparam_nameの属性を代入する。
f not isinstance(param_obj, Parameter):
で属性が、Luigi.Parameter
ではない場合次行。
ってな感じ。