Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Subclassing type vs object in Python3 [duplicate]

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
like image 252
an0o0nym Avatar asked Mar 07 '18 01:03

an0o0nym


People also ask

What is the difference between object and type Python?

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.

Why is it better to use Isinstance?

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.

Are all Python classes subclasses of object?

All the Python built-ins are subclasses of object and I come across many user-defined classes which are too.

What is the difference between the type () and Isinstance () in Python?

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.


1 Answers

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

Everything is an object

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

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

Not everything is a type

That one is fairly obvious

isinstance(1, type) # False
isinstance(isinstance, type) # False
isinstance(int, type) # True

type is its own type

This 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
like image 135
Olivier Melançon Avatar answered Oct 11 '22 15:10

Olivier Melançon