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