64

(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?

Josh Crozier
  • 202,159
  • 50
  • 343
  • 273
quano
  • 17,702
  • 24
  • 94
  • 108

2 Answers2

53

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).

T Tse
  • 680
  • 5
  • 18
ars
  • 106,073
  • 21
  • 135
  • 131
  • 3
    So, you are saying that the *object* class is using \_\_slots\_\_ in one way or another, to prevent assignment of instance members. Is this an assumption or a fact (i.e. is it in the implementation of *object*)? Because the mere absence of \_\dict\_\_ from an *object* instance is not indicative. Instances of the OP's *test1* class show the same missing \_\_dict\_\_ when called with dir(), but allow nevertheless assignment of instance members. – ThomasH Aug 16 '09 at 22:03
  • 1
    @ThomasH, please see the note I added to the answer. – ars Aug 17 '09 at 00:06
4

Good question, my guess is that it has to do with the fact that object is a built-in/extension type.

>>> class test(object):
...  pass
...
>>> test.test = 1
>>> object.test = 1
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can't set attributes of built-in/extension type 'object'

IIRC, this has to do with the presence of a __dict__ attribute or, more correctly, setattr() blowing up when the object doesn't have a __dict__ attribute.

D.Shawley
  • 54,743
  • 9
  • 91
  • 109