Adding attributes to python objects
Question:
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?
Answers:
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.
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?
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.