Вы находитесь на странице: 1из 3

Difference between dir(…) and vars(…).keys() in Python?

Asked 11 years, 7 months ago Active 1 month ago Viewed 20k times

Is there a difference between dir(…) and vars(…).keys() in Python?

71 (I hope there is a difference, because otherwise this would break the "one way to do it" principle... :)

python

35
Share Improve this question Follow edited Jun 11 '09 at 12:28 asked Jun 11 '09 at 9:46
Jason Coon Eric O Lebigot
14.9k 9 35 49 78.6k 40 195 248

11 To be clear, the principle is "One Obvious way to do it", not "only one way to do it". – Ethan Furman Nov 1 '11 at 0:04

3 Answers Active Oldest Votes

Python objects store their instance variables in a dictionary that belongs to the object. vars(x) returns
this dictionary (as does x.__dict__ ). dir(x) , on the other hand, returns a dictionary of x 's "attributes, its
99 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']Overflow to learn, share knowledge, and build your career.
Join Stack Sign up
Share Improve this answer Follow edited Dec 12 '20 at 13:06 answered Jun 11 '09 at 14:57
Boris M.J.
5,655 5 49 59 1,076 7 3

10 I would add that dir() also returns slots, whereas vars() doesn't. – Eric O Lebigot Jun 4 '13 at 13:26

3 Also the output of dir can be customized by implementing the __dir__ magic method: class A: def
__dir__(self): return ['a'] and then you have dir(A()) == ['a'] while vars(A()) == {} . – Bakuriu Sep
13 '16 at 7:49

The documentation has this to say about dir :

27 Without arguments, return the list of names in the current local scope. With an argument, attempt
to return a list of valid attributes for that object.

And this about vars :

Without arguments, return a dictionary corresponding to the current local symbol table. With a
module, class or class instance object as argument (or anything else that has a __dict__
attribute), returns a dictionary corresponding to the object’s symbol table.

If you don't see the difference, maybe this will show you more (grouped for easier reading):

>>> dir(list)
['__add__', '__class__', '__class_getitem__', '__contains__', '__delattr__',
'__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__',
'__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__',
'__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__',
'__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__',
'__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__',
'__str__', '__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend',
'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
>>> vars(list).keys()
dict_keys(['__repr__',
'__hash__',
'__getattribute__',
'__lt__', '__le__', '__eq__', '__ne__', '__gt__', '__ge__',
'__iter__',
'__init__',
'__len__',
'__getitem__', '__setitem__', '__delitem__',
'__add__', '__mul__', '__rmul__', '__contains__', '__iadd__', '__imul__',
'__new__',
'__reversed__', '__sizeof__',
'clear', 'copy', 'append', 'insert', 'extend', 'pop', 'remove', 'index', 'count',
'reverse', 'sort',
'__class_getitem__',
'__doc__'])

If you don't feel like reading through that, dir includes these attributes while vars does not:

>>> set(dir(list)) - vars(list).keys()


{'__class__', '__delattr__', '__dir__', '__format__', '__init_subclass__',
'__reduce__', '__reduce_ex__', '__setattr__', '__str__', '__subclasshook__'}

Note also that dir() 's output is sorted alphabetically, whereas vars() 's output is sorted by the order the
to learn, share knowledge, and build your career.
attributes were defined in.
Share Improve this answer Follow edited Dec 12 '20 at 13:31 answered Jun 11 '09 at 9:53
Boris Paolo Bergantino
5,655 5 49 59 441k 76 504 431

4 I guess that "symbol table" is the key term, here. It is quite hard to find its definition in the official Python
documentation (in fact, I have yet to find it :)). – Eric O Lebigot Apr 21 '11 at 20:17

Apart from Answers given, I would like to add that, using vars() with instances built-in types will give error,
as instances builtin types do not have __dict__ attribute.
2
eg.

In [96]: vars([])
---------------------------------------------------------------------------

TypeError Traceback (most recent call last)


<ipython-input-96-a6cdd8d17b23> in <module>()
----> 1 vars([])
TypeError: vars() argument must have __dict__ attribute

Share Improve this answer Follow edited Sep 13 '16 at 7:35 answered Sep 13 '16 at 6:54
Mangu Singh Rajpurohit
8,434 2 48 70

@SiHa, It's actually the instance of builtin-types, which don't have __dict__ attribute. Thanks for correcting me. I
have updated the answer. – Mangu Singh Rajpurohit Sep 13 '16 at 7:33

Good point. Also, instances of custom classes that implement __slots__ do not have a __dict__ attribute either and
would similarly give an error. – Scott H Feb 1 '17 at 22:31

to learn, share knowledge, and build your career.

Вам также может понравиться