class C(object):
def f(self):
print self.__dict__
print dir(self)
c = C()
c.f()
выход:
{}
['__class__', '__delattr__','f',....]
почему в self нет буквы "f".__dict__
class C(object):
def f(self):
print self.__dict__
print dir(self)
c = C()
c.f()
выход:
{}
['__class__', '__delattr__','f',....]
почему в self нет буквы "f".__dict__
dir()
делает гораздо больше, чем просто ищет __dict__
Прежде всего, dir()
— это метод API, который знает, как использовать такие атрибуты, как __dict__
, для поиска атрибутов объекта.
Однако не все объекты имеют атрибут __dict__
. Например, если вы добавите в свой пользовательский класс атрибут __slots__
, экземпляры этого класса не будет иметь атрибута __dict__
, но dir()
по-прежнему может отображать доступные атрибуты для этих экземпляров:
>>> class Foo(object):
... __slots__ = ('bar',)
... bar = 'spam'
...
>>> Foo().__dict__
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Foo' object has no attribute '__dict__'
>>> dir(Foo())
['__class__', '__delattr__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__slots__', '__str__', '__subclasshook__', 'bar']
То же самое относится ко многим встроенным типам; list
s не имеют атрибута __dict__
, но вы все равно можете перечислить все атрибуты, используя dir()
:
>>> [].__dict__
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'list' object has no attribute '__dict__'
>>> dir([])
['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__delslice__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getslice__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__setslice__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
dir()
делает с экземплярамиЭкземпляры Python имеют свои собственные __dict__
, но и их класс тоже:
>>> class Foo(object):
... bar = 'spam'
...
>>> Foo().__dict__
{}
>>> Foo.__dict__.items()
[('__dict__', <attribute '__dict__' of 'Foo' objects>), ('__weakref__', <attribute '__weakref__' of 'Foo' objects>), ('__module__', '__main__'), ('bar', 'spam'), ('__doc__', None)]
Метод dir()
использует оба этих __dict__
атрибута, и атрибут object
для создания полного списка доступных атрибутов экземпляра, класса и всех предков класса. .
Когда вы устанавливаете атрибуты для класса, экземпляры также видят их:
>>> f = Foo()
>>> f.ham
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Foo' object has no attribute 'ham'
>>> Foo.ham = 'eggs'
>>> f.ham
'eggs'
потому что атрибут добавлен в класс __dict__
:
>>> Foo.__dict__['ham']
'eggs'
>>> f.__dict__
{}
Обратите внимание, что экземпляр __dict__
остается пустым. Поиск атрибутов в объектах Python следует иерархии объектов от экземпляра к типу и к родительским классам для поиска атрибутов.
Только когда вы устанавливаете атрибуты непосредственно в экземпляре, вы увидите атрибут, отраженный в __dict__
экземпляра, в то время как класс __dict__
остается неизменным:
>>> f.stack = 'overflow'
>>> f.__dict__
{'stack': 'overflow'}
>>> 'stack' in Foo.__dict__
False
dir()
не просто ищет __dict__
объекта (который иногда даже не существует), он будет использовать наследие объекта (его класс или тип, а также любые суперклассы или родители этого класса или типа), чтобы дать вам полную информацию. изображение всех доступных атрибутов.
Экземпляр __dict__
— это просто «локальный» набор атрибутов в этом экземпляре, и он не содержит всех атрибутов, доступных в экземпляре. Вместо этого вам нужно также посмотреть на класс и дерево наследования класса.
dir
также будет смотреть на __dir__
, если он реализован, что может возвращать строки для вещей, которые даже не реализованы как формальные свойства или атрибуты, а просто лениво реализованы, например, в __getattr__
.
- person PaulMcG; 16.01.2013
dir()
; это длинный ответ, и мне не нужно было включать эту деталь, чтобы понять суть. :-)
- person Martijn Pieters; 16.01.2013
dir(self)
и self.__dict__
для более краткого ответа.
- person Peterino; 26.02.2017
@Property
getter/setter, он возвращает это общедоступное имя свойства (я понимаю, что эти начальные символы подчеркивания являются просто соглашениями об именах, а не реальными модификаторами доступа). Когда я использую __dict__
, он возвращает только частные атрибуты, например. этот объект DatasourceItem имеет такие свойства, как id
, которые dir
вернет, но __dict__
вернет _id
github.com/tableau/server-client-python/blob/master/
- person Davos; 27.03.2018
property
— это объект-дескриптор, который живет в классе, а не в экземпляре. То, что делает средство получения, установки или удаления свойства, полностью зависит от реализации. Свойство может делать все, что угодно, оно вообще ничего не должно делать с экземпляром. dir()
в экземпляре по-прежнему будут перечислены любые атрибуты класса и любые атрибуты в экземпляре __dict__
, поэтому dir()
в экземпляре DatasourceItem
будет отображаться как свойство connections
, определенное в классе, так и атрибут _connections
в экземпляре. пример.
- person Martijn Pieters; 27.03.2018
DatasourceItem.id
property
живет в классе, а не в экземпляре. instance.id
вызовет метод получения, который затем вернет self._id
, где self._id
— атрибут экземпляра.
- person Martijn Pieters; 27.03.2018
Функция f
принадлежит словарю класса C
. c.__dict__
дает атрибуты, специфичные для экземпляра c
.
>>> class C(object):
def f(self):
print self.__dict__
>>> c = C()
>>> c.__dict__
{}
>>> c.a = 1
>>> c.__dict__
{'a': 1}
C.__dict__
даст атрибуты класса C
, включая функцию f
.
>>> C.__dict__
dict_proxy({'__dict__': <attribute '__dict__' of 'C' objects>, '__module__': '__main__', '__weakref__': <attribute '__weakref__' of 'C' objects>, '__doc__': None, 'f': <function f at 0x0313C1F0>})
Хотя объект может ссылаться на атрибут своего класса (да и на все классы-предки), указанный атрибут класса не становится частью самого связанного dict. Таким образом, хотя это законный доступ к функции f
, определенной в классе C
как c.f()
, он не отображается как атрибут c
в c.__dict__
.
>>> c.a = 1
>>> c.__dict__
{'a': 1}
Классы dir() и dict показывают только определенные функции (методы). Экземпляр dir() показывает данные и методы, а его dict показывает только атрибуты данных, а не методы.
class C2:
... def __init__(self, id):
... self.id = id
... def set(self, len):
... self.len = len
...
c2 = C2("stick")
dir(C2)
['__class__',.., '__init__', 'set']
dir(c2)
['__class__',.., '__init__', 'id', 'set']
C2.__dict__
mappingproxy({'__init__': <function C2.__init__ at 0x000001899C61E9D0>, 'set': <function C2.set at 0x000001899C61ED30>,...})
c2.__dict__
{'id': 'stick'}