Every class in python inherits from the class 'object.' I am wondering about the internal mechanism of the 'object' class implementation. Why cannot the 'object' class be assigned any user-attributes? I am convinced that it is related to memory-management but what if the user thinks of implementing the memory-management himself, why can't he override 'object' class in python? This is based on my interest and want to know about which might not have any programmatic application but would be nice to know the internal feature of the language itself.
3 Answers
Types defined in C can never have user-assigned attributes. If you want to replace object globally then you'll need to iterate over every single class in existence, then replace __builtin__.object to catch all future class creation. And even that isn't reliable since the old object could be bound somewhere else.
Comments
This has been discussed on StackOverflow, but I'm having trouble finding the discussion to link it.
The reason I wondered is because I wanted to simplify this example:
class Box(object): pass box = Box() box.a = "some value" box.b = 42 Here I'm using box as a sort of dictionary, one where the keys can only be identifiers. I do this because it's more convenient to write box.a than box["a"].
I wanted to do this:
box = object() box.a = "some value" # doesn't work The reason is that object is the root of all objects in Python. Any attributes that object has must be in any derived type. If you want to make a large list containing a large number of objects, you want them to be as small as possible so you don't run out of memory. So object itself is minimal.
EDIT: I found the link I was trying to remember:
Comments
If I had to derive the reasoning from first principles, I might think about it in terms of the __slots__ mechanism. Some kinds of classes only need a tiny number of attributes, and the set of attributes is always fixed for every instance, and so the flexibility of a "dict" like user attributes capability would be wasteful of cpu (looking up dynamically named attributes) and space (the overhead of an empty dict, small but non-zero), which can really add up to a lot of overhead if there are a large number of instances.
of course this is exactly the problem the __slots__ mechanism solves. space is allocated on the object for the attributes defined in slots. if there's a __dict__ attribute, non-slot attributes can be found there, and if there's no __dict__ attribute, you get neither the dynamic attributes nor the cost of the unneeded dict object (which is an additional heap object other than the instance itself).
As for why object itself does not have a slot for __dict__, well, even if a subclass indicated that they didn't need the __dict__ slot, if they inherit from a class that does, then the instance must still have a __dict__; if object had a __dict__ then absolutely every class would also pay the price of having a __dict__, even if they didn't need it.
Instead; subclasses get __dict__ (and __weakref__, for analogous reasons) unless they themselves define a __slots__ class attribute.
And why would you need a plain-ol instance of object at all? Do you just need a bag of attributes? well then use a dict. If you actually need an object of some kind with behaviors and attributes, then you are making a subclass anyways.
About the only reason I can ever imagine using object() instead of a subclass of object, is when the only feature of the instance that is of interest is its identity. This would come up when a function takes arguments, and for which None or some other obvious sentinel value should be understood as distinct from the default:
BAR_DEFAULT = object() def foo(bar=BAR_DEFAULT): if bar is BAR_DEFAULT: #... In which case you neither need nor particularly want attributes on the instance of object,
object. (Well, and in Python 3.x, but there all classes are new-style, so it's pointless to mention it).