Subclassing type vs object in Python3 [duplicate]

2020-02-12 19:48发布

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

2条回答
smile是对你的礼貌
2楼-- · 2020-02-12 20:08

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

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 in Python such that

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
查看更多
Root(大扎)
3楼-- · 2020-02-12 20:08

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

Every object is an instance of object including any type of any object. So int is an object and so is str as well as more obvious examples such as 1 and 'asd'. Anything that you can refer to or assign to a variable in Python is an instance of object.

Since object is a type it is an instance of type. This means that object and type 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 between int and 1: the object resulting from 1 is an instance of int. The quirk here is that object and type 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 that type is an object just means that it exists as far as Python's model is concerned. On the other hand object is the base type of all objects so it is a type. As a type it must be an instance of type which like any other object is an instance of object.

As far as the interpreters are implemented: the fact that type is an instance of object is convenient since it maintains "everything is an object" which is useful for e.g. deallocating objects at shutdown. The fact that object is an instance of type is useful since it makes it straight-forward to ensure that it behaves like other type objects.

查看更多
登录 后发表回答