Python objects usually store their instance variables in a dictionary that belongs to the object (except for slots). vars(x)
returns this dictionary (as does x.__dict__
). dir(x)
, on the other hand, returns a dictionary of x
‘s “attributes, its class’s attributes, and recursively the attributes of its class’s base classes.”
When you access an object’s attribute using the dot operator, Python does a lot more than just look up the attribute in that objects dictionary. A common case is when x
is an instance of class C
and you call its method m
:
class C:
def m(self):
print("m")
x = C()
x.m()
The method m
is not stored in x.__dict__
. It is an attribute of the class C
.
When you call x.m()
, Python will begin by looking for m
in x.__dict__
, but it won’t find it. However, it knows that x
is an instance of C
, so it will next look in C.__dict__
, find it there, and call m
with x
as the first argument.
So the difference between vars(x)
and dir(x)
is that dir(x)
does the extra work of looking in x
‘s class (and its bases) for attributes that are accessible from it, not just those attributes that are stored in x
‘s own symbol table. In the above example, vars(x)
returns an empty dictionary, because x
has no instance variables. However, dir(x)
returns
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__',
'__format__', '__ge__', '__getattribute__', '__gt__', '__hash__',
'__init__', '__init_subclass__', '__le__', '__lt__', '__module__',
'__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__',
'__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__',
'm']