pythonattributesinstances

Why can't you add attributes to object in python?


(Written in Python shell)

>>> o = object()
>>> o.test = 1

Traceback (most recent call last):
  File "<pyshell#45>", line 1, in <module>
    o.test = 1
AttributeError: 'object' object has no attribute 'test'
>>> class test1:
    pass

>>> t = test1()
>>> t.test

Traceback (most recent call last):
  File "<pyshell#50>", line 1, in <module>
    t.test
AttributeError: test1 instance has no attribute 'test'
>>> t.test = 1
>>> t.test
1
>>> class test2(object):
    pass

>>> t = test2()
>>> t.test = 1
>>> t.test
1
>>> 

Why doesn't object allow you to add attributes to it?


Solution

  • Notice that an object instance has no __dict__ attribute:

    >>> dir(object())
    ['__class__', '__delattr__', '__doc__', '__getattribute__', '__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__']
    

    An example to illustrate this behavior in a derived class:

    >>> class Foo(object):
    ...     __slots__ = {}
    ...
    >>> f = Foo()
    >>> f.bar = 42
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    AttributeError: 'Foo' object has no attribute 'bar'
    

    Quoting from the docs on slots:

    [...] The __slots__ declaration takes a sequence of instance variables and reserves just enough space in each instance to hold a value for each variable. Space is saved because __dict__ is not created for each instance.

    EDIT: To answer ThomasH from the comments, OP's test class is an "old-style" class. Try:

    >>> class test: pass
    ...
    >>> getattr(test(), '__dict__')
    {}
    >>> getattr(object(), '__dict__')
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    AttributeError: 'object' object has no attribute '__dict__'
    

    and you'll notice there is a __dict__ instance. The object class may not have a __slots__ defined, but the result is the same: lack of a __dict__, which is what prevents dynamic assignment of an attribute. I've reorganized my answer to make this clearer (move the second paragraph to the top).