読者です 読者をやめる 読者になる 読者になる

Pythonのvars()とdir()の違い


このエントリーをはてなブックマークに追加

よくどっちがどっちだったか混乱してしまうので自分用にまとめます。最初に、引数にオブジェクトを渡して呼び出したときの挙動を比較したのち、引数なしで呼び出したときの挙動を比較します。

vars(obj)

2. 組み込み関数 — Python 3.5.2 ドキュメントによると

モジュール、クラス、インスタンス、あるいはそれ以外の dict 属性を持つオブジェクトの、 dict 属性を返します

とあります。例で確かめてみます。

class MyClass:
    def __init__(self):
        self.val1 = 10
        self.val2 = 20

obj = MyClass()
print(vars(obj))
print(obj.__dict__)

この出力は以下の通りです。vars(obj)は、objを辞書として扱ったときの値を返していると解釈できそうです。

{'val1': 10, 'val2': 20}
{'val1': 10, 'val2': 20}

dir(obj)

2. 組み込み関数 — Python 3.5.2 ドキュメントによると

そのオブジェクトの有効な属性のリストを返そうと試みます

とあります。以下は、先ほどのvars()をdir()で置換しただけのコードです。

class MyClass:
    def __init__(self):
        self.val1 = 10
        self.val2 = 20

obj = MyClass()
print(dir(obj))

この出力は以下の通りです。

['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'val1', 'val2']

このように、オブジェクトが持つ属性のみならず、オブジェクトが属しているクラスが持つ属性をも含んだリストが返ってきます。dir()関数の使用用途としては、プログラマが対話的にオブジェクトが持つ属性の一覧を覗いて、使えそうなものを探ることのようです。再び2. 組み込み関数 — Python 3.5.2 ドキュメントから引用します。

注釈 dir() は主に対話プロンプトでの使用に便利なように提供されているので、厳密性や一貫性を重視して定義された名前のセットというよりも、むしろ興味を引くような名前のセットを返そうとしま す。また、この関数の細かい動作はリリース間で変わる可能性があります。例えば、引数がクラスであるとき、メタクラス属性は結果のリストに含まれません。

vars()

引数なしでvars()を呼ぶと、「locals() のように振る舞います」とのこと。locals()は、「現在のローカルシンボルテーブルを表す辞書を更新して返します」とのこと。以下のコード

class MyClass:
    def __init__(self):
        self.val1 = 10
        self.val2 = 20

obj = MyClass()
print(vars())

の実行例は以下です。

{'__spec__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x00000289CD407940>, '__file__': '/path/to/somewhere.py', '__cached__': None, '__builtins__': <module 'builtins' (built-in)>, '__name__': '__main__', 'obj': <__main__.MyClass object at 0x00000289CD4698D0>, 'MyClass': <class '__main__.MyClass'>, '__doc__': None, '__package__': None}

dir()

引数なしでvars()を呼ぶと、「現在のローカルスコープにある名前のリストを返します。」とのこと。

class MyClass:
    def __init__(self):
        self.val1 = 10
        self.val2 = 20

obj = MyClass()
print(dir())

の実行例は以下です。

['MyClass', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'obj']

引数なしvars()の戻り値である辞書のkeys()と同じ結果のように見えます。

参考URL