Разница между dir (…) и vars (…) .keys () в Python? - PullRequest
49 голосов
/ 11 июня 2009

Есть ли разница между dir(…) и vars(…).keys() в Python?

(Я надеюсь, что есть разница, потому что в противном случае это нарушило бы принцип "одного способа сделать это" ...:)

Ответы [ 3 ]

79 голосов
/ 11 июня 2009

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 начнет поиск m в x.__dict__, но не найдет его. Тем не менее, он знает, что 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']
24 голосов
/ 11 июня 2009

В документации есть это, чтобы сказать о 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__'])
3 голосов
/ 13 сентября 2016

Помимо данных ответов, я хотел бы добавить, что использование 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...