This answer explains well the __dict__
attribute:
Python objects store their instance variables in a dictionary that belongs to the object. vars(x) returns this dictionary (as does x.__dict__). dir(x), on the other hand, returns a dictionary of x's "attributes, its class's attributes, and recursively the attributes of its class's base classes."
So let's see this in practice:
import xml.etree.ElementTree as ET
e = ET.Element(None)
print(e.__dict__)
# Raises AttributeError: 'xml.etree.ElementTree.Element' object has no attribute '__dict__'
But why, since e
does have attributes?
import xml.etree.ElementTree as ET
e = ET.Element(None)
print(e.tag)
# Outputs None
e = ET.Element("my-tag")
print(e.tag)
# Outputs my-tag
Let's see the attributes from its class:
import xml.etree.ElementTree as ET
print(ET.Element.__dict__)
This will output
mappingproxy({'__copy__': <method '__copy__' of 'xml.etree.ElementTree.Element' objects>,
'__deepcopy__': <method '__deepcopy__' of 'xml.etree.ElementTree.Element' objects>,
'__delitem__': <slot wrapper '__delitem__' of 'xml.etree.ElementTree.Element' objects>,
'__doc__': None,
'__getattribute__': <slot wrapper '__getattribute__' of 'xml.etree.ElementTree.Element' objects>,
'__getitem__': <slot wrapper '__getitem__' of 'xml.etree.ElementTree.Element' objects>,
'__getstate__': <method '__getstate__' of 'xml.etree.ElementTree.Element' objects>,
'__init__': <slot wrapper '__init__' of 'xml.etree.ElementTree.Element' objects>,
'__len__': <slot wrapper '__len__' of 'xml.etree.ElementTree.Element' objects>,
'__new__': <built-in method __new__ of type object at 0x92a480>,
'__repr__': <slot wrapper '__repr__' of 'xml.etree.ElementTree.Element' objects>,
'__setitem__': <slot wrapper '__setitem__' of 'xml.etree.ElementTree.Element' objects>,
'__setstate__': <method '__setstate__' of 'xml.etree.ElementTree.Element' objects>,
'__sizeof__': <method '__sizeof__' of 'xml.etree.ElementTree.Element' objects>,
'append': <method 'append' of 'xml.etree.ElementTree.Element' objects>,
'attrib': <attribute 'attrib' of 'xml.etree.ElementTree.Element' objects>,
'clear': <method 'clear' of 'xml.etree.ElementTree.Element' objects>,
'extend': <method 'extend' of 'xml.etree.ElementTree.Element' objects>,
'find': <method 'find' of 'xml.etree.ElementTree.Element' objects>,
'findall': <method 'findall' of 'xml.etree.ElementTree.Element' objects>,
'findtext': <method 'findtext' of 'xml.etree.ElementTree.Element' objects>,
'get': <method 'get' of 'xml.etree.ElementTree.Element' objects>,
'getchildren': <method 'getchildren' of 'xml.etree.ElementTree.Element' objects>,
'getiterator': <method 'getiterator' of 'xml.etree.ElementTree.Element' objects>,
'insert': <method 'insert' of 'xml.etree.ElementTree.Element' objects>,
'items': <method 'items' of 'xml.etree.ElementTree.Element' objects>,
'iter': <method 'iter' of 'xml.etree.ElementTree.Element' objects>,
'iterfind': <method 'iterfind' of 'xml.etree.ElementTree.Element' objects>,
'itertext': <method 'itertext' of 'xml.etree.ElementTree.Element' objects>,
'keys': <method 'keys' of 'xml.etree.ElementTree.Element' objects>,
'makeelement': <method 'makeelement' of 'xml.etree.ElementTree.Element' objects>,
'remove': <method 'remove' of 'xml.etree.ElementTree.Element' objects>,
'set': <method 'set' of 'xml.etree.ElementTree.Element' objects>,
'tag': <attribute 'tag' of 'xml.etree.ElementTree.Element' objects>,
'tail': <attribute 'tail' of 'xml.etree.ElementTree.Element' objects>,
'text': <attribute 'text' of 'xml.etree.ElementTree.Element' objects>})
So tag
is not an instance variable, it's a class variable, that's why it's present in the class' __dict__
, not in the e
's __dict__
.
In fact, the instance of ET.Element
(e
) does not have any instance variables, but only class variables defined in the ET.Element
.
I'm not sure about why the library class doesn't have a __dict__
and a user defined class has, but I think it's related to this answer:
[...] These are usually natively coded (i.e. written in C) - and the __dict__ attribute would have to be explicitly created - so unlike classes coded in Python - one have to go out of his way to allow __dict__ in these classes, while for Python code, the detour is on avoiding __dict__.