すのふら

すのふら

日々の備忘録

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ではない場合次行。

ってな感じ。