Python中的dir(…)和vars(…).keys()之间的区别?

Python中的dir(…)vars(…).keys()之间有区别吗?

(我希望有一个区别,否则这将打破“做到这一点”的原则… 🙂

Python对象将其实例variables存储在属于对象的字典中。 vars(x)返回这个字典(同x.__dict__ )。 另一方面, dir(x)返回一个字典x的属性,它的类的属性,recursion的类的基类的属性。

当你使用点运算符访问一个对象的属性时,python所做的不仅仅是查找对象字典中的属性。 一个常见的情况是,当xC类的一个对象时,你可以调用一个方法m

 class C(object): def m(self): print "m" x = C() xm() 

方法m不存储在x.__dict__ 。 这是C类的一个属性。 当你调用xm() ,python将开始在x.__dict__寻找m,但是它不会find它。 但是,它知道xC一个实例,所以它将接着查看C.__dict__ ,在那里find它,并用x作为第一个参数调用m

因此, vars(x)dir(x)之间的区别在于, dir(x)x的类(及其基类)中查找可从中访问的属性,而不仅仅是存储的属性在x的自己的符号表中。 在上面的例子中, vars(x)返回一个空的字典,因为x没有实例variables。 但是, dir(x)返回

 ['__class__', '__delattr__', '__dict__', '__doc__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__', '__weakref__', 'm'] 

这个文档有关于dir说法:

没有参数,返回当前本地作用域中的名称列表。 使用参数尝试返回该对象的有效属性列表。

而这个关于vars

如果没有参数,则返回与当前本地符号表相对应的字典。 使用模块,类或类实例对象作为参数(或其他任何具有__dict__属性的对象),将返回与该对象的符号表对应的字典。

如果你看不出有什么不同,也许这会给你更多的印象:

 >>> dir(list) ['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__delsli ce__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getit em__', '__getslice__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__r educe__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__' , '__setitem__', '__setslice__', '__sizeof__', '__str__', '__subclasshook__', 'a ppend', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort' ] >>> vars(list).keys() ['__getslice__', '__getattribute__', 'pop', 'remove', '__rmul__', '__lt__', '__s izeof__', '__init__', 'count', 'index', '__delslice__', '__new__', '__contains__ ', 'append', '__doc__', '__len__', '__mul__', 'sort', '__ne__', '__getitem__', ' insert', '__setitem__', '__add__', '__gt__', '__eq__', 'reverse', 'extend', '__d elitem__', '__reversed__', '__imul__', '__setslice__', '__iter__', '__iadd__', ' __le__', '__repr__', '__hash__', '__ge__'] 

如果你不想阅读, dir包含这些属性,而vars不包括:

 >>> set(dir(list)).difference(vars(list).keys()) set(['__str__', '__reduce__', '__subclasshook__', '__setattr__', '__reduce_ex__' , '__format__', '__class__', '__delattr__']) 

除了给出的答案,我想补充说,使用vars()与实例内置types会给出错误,因为内置types实例没有__dict__属性。

例如。

 In [96]: vars([]) --------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-96-a6cdd8d17b23> in <module>() ----> 1 vars([]) TypeError: vars() argument must have __dict__ attribute