2009-06-11 24 views
41

Python中的dir(…)vars(…).keys()之間有區別嗎?Python中的dir(...)和vars(...).keys()之間的區別?

(我希望是有區別的,否則這將打破「做到這一點的一種方式」的原則... :)

+8

要明確,原則是「一個*明顯的*做到這一點」,而不是「*只有*一種做法」。 – 2011-11-01 00:04:14

+0

@EthanFurman:right :) – EOL 2011-11-01 09:36:31

回答

67

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__,在那裏找到它,並將mx作爲第一個參數。

所以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'] 
+6

我會補充說'dir()`也返回插槽,而'vars()`不會。 – EOL 2013-06-04 13:26:50

23

的文檔已經這樣說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__']) 
+1

我想這裏的「符號表」是關鍵術語。在官方的Python文檔中很難找到它的定義(事實上,我還沒有找到:))。 – EOL 2011-04-21 20:17:03

3

除了給出答案,我想補充的是,使用瓦爾()的情況下,內置的類型將給錯誤,因爲實例內建類型沒有__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 
相關問題