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
Object can be any Python class instance which may or may not be user defined. But, when you are talking about a type, it refers to the default objects/collections like a list/tuple/dict/int/str etc.
Conclusions. isinstance is usually the preferred way to compare types. It's not only faster but also considers inheritance, which is often the desired behavior. In Python, you usually want to check if a given object behaves like a string or a list, not necessarily if it's exactly a string.
All the Python built-ins are subclasses of object and I come across many user-defined classes which are too.
type() returns the type of the object you put in as an argument, and is usually not useful unless compared with a real type (such as type(9) == int ). isinstance() returns a boolean - true or false - based on whether the object is of given type.
There is no cross-inheritance between object
and type
. In fact, cross-inheritance is impossible.
# A type is an object
isinstance(int, object) # True
# But an object is not necessarily a type
isinstance(object(), type) # False
What is true in Python is that...
Absolutly everything, object
is the only base type.
isinstance(1, object) # True
isinstance('Hello World', object) # True
isinstance(int, object) # True
isinstance(object, object) # True
isinstance(type, object) # True
Everything has a type, either built-in or user-defined, and this type can be obtained with type
.
type(1) # int
type('Hello World') # str
type(object) # type
That one is fairly obvious
isinstance(1, type) # False
isinstance(isinstance, type) # False
isinstance(int, type) # True
type
is its own typeThis is the behaviour which is specific to type
and that is not reproducible for any other class.
type(type) # type
In other word, type
is the only object X
in Python such that type(X) is X
type(type) is type # True
# While...
type(object) is object # False
This 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...
# This defines a class
class Foo(object):
pass
# Its instances are not types
isinstance(Foo(), type) # False
# While this defines a metaclass
class Bar(type):
pass
# Its instances are types
MyClass = Bar('MyClass', (), {})
isinstance(MyClass, type) # True
# And it is a class
x = MyClass()
isinstance(x, MyClass) # True
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With