41

It's a thing that bugged me for a while. Why can't I do:

>>> a = ""
>>> a.foo = 2
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'str' object has no attribute 'foo'

...while I can do the following?

>>> class Bar():
...     pass
... 
>>> a = Bar()
>>> a.foo = 10 #ok!

What's the rule here? Could you please point me to some description?

ThiefMaster
  • 310,957
  • 84
  • 592
  • 636
mik01aj
  • 11,928
  • 15
  • 76
  • 119

1 Answers1

60

You can add attributes to any object that has a __dict__.

  • x = object() doesn't have it, for example.
  • Strings and other simple builtin objects also don't have it.
  • Classes using __slots__ also do not have it.
  • Classes defined with class have it unless the previous statement applies.

If an object is using __slots__ / doesn't have a __dict__, it's usually to save space. For example, in a str it would be overkill to have a dict - imagine the amount of bloat for a very short string.

If you want to test if a given object has a __dict__, you can use hasattr(obj, '__dict__').

This might also be interesting to read:

Some objects, such as built-in types and their instances (lists, tuples, etc.) do not have a __dict__. Consequently user-defined attributes cannot be set on them.

Another interesting article about Python's data model including __dict__, __slots__, etc. is this from the python reference.

ThiefMaster
  • 310,957
  • 84
  • 592
  • 636