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

时间:2009-06-11 09:46:52

标签: python

Python中的dir(…)vars(…).keys()之间是否存在差异?

(我希望有一点不同,因为否则这会打破“一种做法”的原则......)

3 个答案:

答案 0 :(得分:77)

Python对象将其实例变量存储在属于该对象的字典中。 vars(x)返回此字典(x.__dict__也是如此)。另一方面,dir(x)返回x的“属性字典,其类的属性,以及递归其类的基类的属性。”

当您使用点运算符访问对象的属性时,python不仅仅在该对象字典中查找属性。一个常见的情况是x是类C的对象,并且您在其上调用方法m

class C(object):
    def m(self):
        print "m"

x = C()
x.m()

方法m未存储在x.__dict__中。它是类C的属性。 当你调用x.m()时,python将首先在x.__dict__中查找m,但它找不到它。但是,它知道xC的一个实例,因此接下来会在C.__dict__中查找,在那里找到它,然后使用m调用x第一个论点。

因此vars(x)dir(x)之间的区别在于dir(x)执行额外的工作,即在x的类(及其基础)中查找可访问的属性从中,不只是那些存储在x自己的符号表中的属性。在上面的示例中,vars(x)返回一个空字典,因为x没有实例变量。但是,dir(x)会返回

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

答案 1 :(得分:24)

文档说明了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__'])

答案 2 :(得分:3)

除了给出的答案之外,我想补充一点,使用带有实例内置类型的vars()会产生错误,因为内置类型的实例没有__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