11

If my understanding of the Python data model is correct, both classes and class instances have associated __dict__ objects which contain all the attributes. However, I'm a little confused as to why certain class instances, such as instances of str for example, don't have a __dict__ attribute.

If I create a custom class:

class Foo:
     def __init__(self):
             self.firstname = "John"
             self.lastname = "Smith"

Then I can get the instance variables by saying:

>>> f = Foo()
>>> print(f.__dict__)
{'lastname': 'Smith', 'firstname': 'John'}

But if I try to do the same with an instance of the built-in str, I get:

>>> s = "abc"
>>> print(s.__dict__)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'str' object has no attribute '__dict__'

So, why don't instances of str have a __dict__ attribute?

Channel72
  • 24,139
  • 32
  • 108
  • 180
  • 2
    To elaborate on this, if every dict had a `__dict__`, then there would have to be `__dict__.__dict__` as well -- how deep should the recursion go? – Robin Davis Jan 29 '16 at 09:29

2 Answers2

14

Instances of types defined in C don't have a __dict__ attribute by default.

Ignacio Vazquez-Abrams
  • 776,304
  • 153
  • 1,341
  • 1,358
2

Just to add to this:

You can get the equivalent of a read only __dict__ using this:

{s:getattr(x, s) for s in dir(x)}

EDIT: Please note that this may contain more entries than __dict__. To avert this, you may use this as a workaround:

{s:getattr(x, s) for s in dir(x) if not s.startswith("__")}
  • It should be `{s:getattr(x,s) for s in dir(x)}`, and it incudes entries not in the `__dict__`. – cowlinator Feb 23 '21 at 03:21
  • Thanks, that's a big improvement, and would now work in many cases. However, if the object contains functions, `__dict__` will not return those functions, but `{s:getattr(x, s) for s in dir(x) if not s.startswith("__")}` will. Example: `class A(): def b(): pass` – cowlinator Feb 23 '21 at 23:02
  • It will also list class-level variables that `__dict__` wont list. – cowlinator Feb 23 '21 at 23:37