Python中的dir(…)
和vars(…).keys()
之间有区别吗?Python中的dir(...)和vars(...).keys()之间的区别?
(我希望是有区别的,否则这将打破“做到这一点的一种方式”的原则... :)
Python中的dir(…)
和vars(…).keys()
之间有区别吗?Python中的dir(...)和vars(...).keys()之间的区别?
(我希望是有区别的,否则这将打破“做到这一点的一种方式”的原则... :)
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,但不会找到它。但是,它知道x
是C
的一个实例,因此它将接着查看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']
我会补充说'dir()`也返回插槽,而'vars()`不会。 – EOL 2013-06-04 13:26:50
的文档已经这样说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__'])
我想这里的“符号表”是关键术语。在官方的Python文档中很难找到它的定义(事实上,我还没有找到:))。 – EOL 2011-04-21 20:17:03
除了给出答案,我想补充的是,使用瓦尔()的情况下,内置的类型将给错误,因为实例内建类型没有__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
要明确,原则是“一个*明显的*做到这一点”,而不是“*只有*一种做法”。 – 2011-11-01 00:04:14
@EthanFurman:right :) – EOL 2011-11-01 09:36:31