Python中的dir(…)和vars(…).keys()之间的区别?
Python中的dir(…)
和vars(…).keys()
之间有区别吗?
(我希望有一个区别,否则这将打破“做到这一点”的原则… 🙂
Python对象将其实例variables存储在属于对象的字典中。 vars(x)
返回这个字典(同x.__dict__
)。 另一方面, dir(x)
返回一个字典x
的属性,它的类的属性,recursion的类的基类的属性。
当你使用点运算符访问一个对象的属性时,python所做的不仅仅是查找对象字典中的属性。 一个常见的情况是,当x
是C
类的一个对象时,你可以调用一个方法m
。
class C(object): def m(self): print "m" x = C() xm()
方法m
不存储在x.__dict__
。 这是C
类的一个属性。 当你调用xm()
,python将开始在x.__dict__
寻找m,但是它不会find它。 但是,它知道x
是C
一个实例,所以它将接着查看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