I've been reading about metaclasses and I got lost when it came to type
and object
classes.
I understand that they are at the top of the hierarchy and they are implemented in C code.
I also understand that type
inherits from object
and that object
is an instance of type
.
In one of the answers I've found on SO, someone said - in reagards to object-type
relationship - that:
This kind of mutual inheritance is not normally possible, but that's the way it is for these fundamental types in Python: they break the rules.
My question is why is it implemented this way, what is purpose of such implementation? What problems does it solve/what are the benefits of this design? Couldn't it be just type
or just object
class that is at the top of the hierarchy that every class inherits from?
Finally, is there any difference between subclassing from object
vs subclassing from type
, and when would I want to use one over the other?
class Foo(object):
pass
vs
class Foo(type):
pass
There is no cross-inheritance between
object
andtype
. In fact, cross-inheritance is impossible.What is true in Python is that...
Everything is an object
Absolutly everything,
object
is the only base type.Everything has a type
Everything has a type, either built-in or user-defined, and this type can be obtained with
type
.Not everything is a type
That one is fairly obvious
type
is its own typeThis is the behaviour which is specific to
type
and that is not reproducible for any other class.In other word,
type
is the only object in Python such thatThis is because
type
is the only built-in metaclass. A metaclass is simply a class, but its instances are also classes themselves. So in your example...In Python everything is an object. Also every object has a type. In fact the type of an object is also an object and therefore must also have its own type. Types have a special type that is called
type
. This (like any other type) is an object and is therefore an instance ofobject
.Every object is an instance of
object
including any type of any object. Soint
is an object and so isstr
as well as more obvious examples such as1
and'asd'
. Anything that you can refer to or assign to a variable in Python is an instance ofobject
.Since
object
is a type it is an instance oftype
. This means thatobject
andtype
are both instances of each other. This is not "inheritance" regardless of what the other answer you linked says. The relationship is the same as the relationship betweenint
and1
: the object resulting from1
is an instance ofint
. The quirk here is thatobject
andtype
are both instances of each other.From a Python perspective these two mean different things. The
object
type has an ontological role: everything is an object (and nothing else exists). So to say thattype
is an object just means that it exists as far as Python's model is concerned. On the other handobject
is the base type of all objects so it is a type. As a type it must be an instance oftype
which like any other object is an instance ofobject
.As far as the interpreters are implemented: the fact that
type
is an instance ofobject
is convenient since it maintains "everything is an object" which is useful for e.g. deallocating objects at shutdown. The fact thatobject
is an instance oftype
is useful since it makes it straight-forward to ensure that it behaves like other type objects.