Python3中的子类化类型与对象[重复]

Posted

技术标签:

【中文标题】Python3中的子类化类型与对象[重复]【英文标题】:Subclassing type vs object in Python3 [duplicate] 【发布时间】:2018-08-14 23:59:43 【问题描述】:

我一直在阅读有关元类的文章,但当谈到 typeobject 类时,我迷路了。

我知道它们位于层次结构的顶部,并且是用 C 代码实现的。 我也知道type 继承自object 并且objecttype 的一个实例。

在我在 SO 上找到的 answers 之一中,有人说 - 关于 object-type 关系 - 那:

这种相互继承通常是不可能的,但这就是 Python 中这些基本类型的方式:它们违反了规则。

我的问题是为什么要这样实施,这样实施的目的是什么?它解决了什么问题/这种设计有什么好处?难道不能只是 type 或只是 object 类,它位于每个类继承的层次结构的顶部吗?

最后,从object 子类化与从type 子类化之间有什么区别,我什么时候想使用其中一个?

class Foo(object):
    pass

class Foo(type):
    pass

【问题讨论】:

这个答案很有误导性。没有相互继承;答案不能很好地传达实例和子类关系之间的区别。 type 是 Python 中的基本元类。 (每个类都是一个对象,一个类的类就是它的元类。)你不应该继承type,除非你有意创建一个元类。 【参考方案1】:

objecttype 之间没有交叉继承。事实上,交叉继承是不可能的。

# A type is an object
isinstance(int, object) # True

# But an object is not necessarily a type
isinstance(object(), type) # False

在 Python 中的真实情况是......

一切都是对象

绝对所有,object 是唯一的基本类型。

isinstance(1, object) # True
isinstance('Hello World', object) # True
isinstance(int, object) # True
isinstance(object, object) # True
isinstance(type, object) # True

一切都有类型

任何东西都有一个类型,可以是内置的,也可以是用户自定义的,这个类型可以通过type获得。

type(1) # int
type('Hello World') # str
type(object) # type

并非所有事物都是类型

这个很明显

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

type 是它自己的类型

这是type 特有的行为,对于任何其他类都不可重现。

type(type) # type

换句话说,type 是 Python 中唯一的对象 X,使得 type(X) is X

type(type) is type # True

# While...
type(object) is object # False

这是因为type 是唯一的内置元类。元类只是一个类,但它的实例也是类本身。所以在你的例子中......

# 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

【讨论】:

注意:这里的一些“总是”声明仅适用于 Python 3;在 Python 2 中,旧式类有一个完全独立的类型层次结构(type(x) 其中x 是旧式类的一个实例,总是毫无用处地告诉你,该实例的类型是instance,而不是它是一个实例的类)。 以上所有内容都是正确的,我仔细措辞,所以它在 Python2 和 3 中都是如此。问题是type(Foo()) is Foo 总是正确的。您的示例正确地表明即使isinstance(Foo(), Foo) 为真,它也不是。其余的仍然是正确的,一切都是对象,一切都有类型,type 是唯一属于自己类型的对象。但是,如果我错了,请纠正我! 啊,是的。在重新检查时,即使是旧式类的实例也声称是object 的实例,尽管从object 继承是您创建新式类的方式。不知何故,isinstance(Foo(), object) 为真,即使issubclass(Foo, object) 为假,因为instance 本身是object 的子类。 Py2 类型系统中的hackery 有时有点神奇。 :-) 我还可以在“所有都是对象”下添加:isinstance(type, object) # True【参考方案2】:

在 Python 中,一切都是对象。每个对象也都有一个类型。事实上,对象的类型也是一个对象,因此也必须有自己的类型。类型有一个特殊的类型,称为type。这(与任何其他类型一样)是一个对象,因此是 object 的一个实例。

Every 对象是object 的一个实例,包括任何对象的任何类型。所以int是一个对象,str也是一个对象,还有更明显的例子,比如1'asd'。您可以在 Python 中引用或分配给变量的任何内容都是 object 的实例。

由于object 是一个类型,它是type 的一个实例。这意味着objecttype 都是彼此的实例。无论您链接的其他答案是什么,这都不是“继承”。该关系与int1 之间的关系相同:1 产生的对象是int 的一个实例。这里的怪癖是objecttype 都是彼此的实例。

从 Python 的角度来看,这两个含义不同。 object 类型具有本体论的作用:一切都是对象(不存在其他任何东西)。所以说type 是一个对象只是意味着它存在 就Python 的模型而言。另一方面,object 是所有对象的基本类型,因此它是一种类型。作为一种类型,它必须是 type 的实例,与任何其他对象一样,它也是 object 的实例。

就解释器的实现而言:typeobject 的一个实例这一事实很方便,因为它维护“一切都是对象”,这对于例如在关闭时释放对象。 objecttype 的一个实例这一事实很有用,因为它可以直接确保它的行为与其他类型对象一样。

【讨论】:

这是很好的信息,有没有更一般的官方知识体系?

以上是关于Python3中的子类化类型与对象[重复]的主要内容,如果未能解决你的问题,请参考以下文章

使用PyQt(QMainWindow)使用多重继承进行子类化时python中的MRO [重复]

python 继承机制(子类化内置类型)

属性类型与访问器类型不匹配(子类化时)

创建一个基类方法,根据调用该方法的子类实例化一个新的子类对象

了解 JSONEncoder 的子类化

类与继承