So here goes my inaugural post: not all objects are created equal in python. New-style classes (which are only "new" in the sense they were introduced in python 2.2 which is quite old now) all inherit from the base
object class. For example, consider the following simple class:
>>> class MyObject(object):
... pass
This is about as simple a class as you can make in Python; MyObject inherits all of its behaviour from the
object base class. Now, lets set an attribute on an instance of our new class:
>>> b = MyObject()
>>> b.myattr = 42
>>> print b.myattr
42
Nothing fancy here. But recall that our
MyObject class adds nothing to the base object class, implying that the ability to set arbitrary attributes on an instance must originate with the object class's implementation. Let's give it a try:
>>> a = object()
>>> a.myattr = 42
Traceback (most recent call last):
File "", line 1, in
AttributeError: 'object' object has no attribute 'myattr'
>>> setattr(a, 'myattr', 42)
Traceback (most recent call last):
File "", line 1, in
AttributeError: 'object' object has no attribute 'myattr'
What is going on here? We were able to set attributes on instances of
MyObject, but not on instances of object itself? That's odd: MyObject inherits all of its behaviour from object, so they should be exactly the same!My first guess was that the
object class had a __slots__ attribute restricting which attributes could be set on it (see this article for an explanation of __slots__). One of the properties of __slots__ is that, unlike most other class attributes, it is not inherited by subclasses. Which would explain why we can set arbitrary attributes on instances of MyObject, which is a subclass of object, but not on instances of object itself. However, to my surprise, object does not define a __slots__ attribute:
>>> '__slots__' in dir(object)
False
>>> dir(object)
['__class__', '__delattr__', '__doc__', '__getattribute__',
'__hash__', '__init__', '__new__', '__reduce__',
'__reduce_ex__', '__repr__', '__setattr__', '__str__']
Look: no
__slots__! So that isn't it.As far as I can tell, the fact instances of
object do not allow attributes to be set on them is simply an implementation artifact. They should, but they don't. Go figure. Luckily, there is seldom need to create instances of object directly; the class really just exists as a base class for deriving new-style classes. But I do still find it odd somehow subclassing object adds functionality not present in the base class.