python的type和object之间是怎么一种关系?
程序员文章站
2022-04-27 09:50:45
...
是初学者请勿喷啊
两个是互为实例的关系,但不是互为子类的关系,只有type是object的子类,反之则不成立。大牛说两者是蛋生鸡鸡生蛋的关系,但我还是不明白,有懂的麻烦解释一下,希望不要给出外文的链接。python为什么设计出两个,去掉 一个行不行?
object 和 type的关系很像鸡和蛋的关系,先有object还是先有type没法说,obejct和type是共生的关系,必须同时出现的。
在看下去之前,也要请先明白,在Python里面,所有的东西都是对象的概念。
在面向对象体系里面,存在两种关系:
- 父子关系,即继承关系,表现为子类继承于父类,如『蛇』类继承自『爬行动物』类,我们说『蛇是一种爬行动物』,英文说『snake is a kind of reptile』。在python里要查看一个类型的父类,使用它的__bases__属性可以查看。
- 类型实例关系,表现为某个类型的实例化,例如『萌萌是一条蛇』,英文说『萌萌 is an instance of snake』。在python里要查看一个实例的类型,使用它的__class__属性可以查看,或者使用type()函数查看。
这两种关系使用下面这张图简单示意,继承关系使用实线从子到父连接,类型实例关系使用虚线从实例到类型连接:
我们将使用一块白板来描述一下Python里面对象的关系,白板划分成三列:
先来看看type和object:
>>> object
>>> type
它们都是type的一个实例,表示它们都是类型对象。
在Python的世界中,object是父子关系的顶端,所有的数据类型的父类都是它;type是类型实例关系的顶端,所有对象都是它的实例的。它们两个的关系可以这样描述:
- object是一个type,object is and instance of type。即Object是type的一个实例。
>>> object.__class__
>>> object.__bases__ # object 无父类,因为它是链条顶端。
()
- type是一种object, type is kind of object。即Type是object的子类。
>>> type.__bases__
(,)
>>> type.__class__ # type的类型是自己
此时,白板上对象的关系如下图:
我们再引入list, dict, tuple 这些内置数据类型来看看:
>>> list.__bases__
(,)
>>> list.__class__
>>> dict.__bases__
(,)
>>> dict.__class__
>>> tuple.__class__
>>> tuple.__bases__
(,)
它们的父类都是object,类型都是type。
再实例化一个list看看:
>>> mylist = [1,2,3]
>>> mylist.__class__
>>> mylist.__bases__
Traceback (most recent call last):
File "", line 1, in
AttributeError: 'list' object has no attribute '__bases__'
实例化的list的类型是, 而没有了父类。
把它们加到白板上去:
白板上的虚线表示源是目标的实例,实线表示源是目标的子类。即,左边的是右边的类型,而上面的是下面的父亲。
虚线是跨列产生关系,而实线只能在一列内产生关系。除了type和object两者外。
当我们自己去定个一个类及实例化它的时候,和上面的对象们又是什么关系呢?试一下:
>>> class C(object):
... pass
...
>>> C.__class__
>>> C.__bases__
(,)
实例化
>>> c = C()
>>> c.__class__
>>> c.__bases__
Traceback (most recent call last):
File "", line 1, in
AttributeError: 'C' object has no attribute '__bases__'
这个实例化的C类对象也是没有父类的属性的。
再更新一下白板:
白板上的第一列,目前只有type,我们先把这列的东西叫Type。
白板上的第二列,它们既是第三列的类型,又是第一列的实例,我们把这列的对象叫TypeObject。
白板上的第三列,它们是第二列类型的实例,而没有父类(__bases__)的,我们把它们叫Instance。
你以为事情就这样完了?不。。看见type孤零零在第一列其实不是那么舒服。。我们给它整几个玩伴看看。但要怎么整呢?要属于第一列的,必须是type的子类,那么我们只需要继承type来定义类就可以了:
>>> class M(type):
... pass
...
>>> M.__class__
>>> M.__bases__
(,)
>>>
嗯嗯,M类的类型和父类都是type。这个时候,我们可以把它归到第一列去。那么,要怎么样实例化M类型呢?实例化后它应该出现在那个列?嗯嗯,好吧,刚才你一不小心创建了一个元类,MetaClass!即类的类。如果你要实例化一个元类,那还是得定义一个类:
>>> class TM(object):
... __metaclass__ = M # 这样来指定元类。
...
...
>>> TM.__class__
# 这个类不再是type类型,而是M类型的。
>>> TM.__bases__
(,)
好了,现在TM这个类就是出现在第二列的。
再总结一下:
第一列,元类列,type是所有元类的父亲。我们可以通过继承type来创建元类。
第二列,TypeObject列,也称类列,object是所有类的父亲,大部份我们直接使用的数据类型都存在这个列的。
第三列,实例列,实例是对象关系链的末端,不能再被子类化和实例化。
到现在为止,Python类型的秘密已经说穿了,不一小心连元类也暴露了。哎。慢慢消化吧,信息量很大。
如果转述版看不懂,那么去啃一啃原文的吧:(Python Types and Objects)
=============更新=============
更新更新。。回答一下题主在问题后面说的为什么要有两个,而不是一个。
如果type和object只保留一个,那么一定是object。只有object 时,第一列将不复存在,只剩下二三列,第二列表示类型,第三列表示实例,这个和大部分静态语言的类型架构类似,如java 。
这样的架构将让python 失去一种很重要的动态特性--动态创建类型。本来,类(第二列的同学)在Python里面是一个对象(typeobject),对象是可以在运行时动态修改的,所以我们能在你定义一个类之后去修改他的行为或属性!拿掉第一列后,第二列变成了纯类型,写成怎样的,运行时行为就怎样。在这一点上,并不比静态语言有优势。
所以,以上! 那我就来补充个跟实现思路相关的传送门吧:先有Class还是先有Object? - RednaxelaFX 的回答
图对不对先不管。我们先来看看 type 和 object 分别是什么。
type 实际上是:
简单的说,很多运行时体系(不一定是针对某种语言)都提供在运行时获取类型信息的功能,那么获取出来的是什么东西呢?获取出来的是一个描述类型信息的对象。那么所有描述类型信息的对象,都是“类型”这个类型的实例。这个type类型不是类型本身,而是用于描述类型的对象实例,类型本身是一种抽象的信息,type类的实例对象是它具体的信息载体。既然type类型也是一种类型,那么它是公共根类型object的一个派生,也就是合情合理的设计了。
反过来,object 类型并不依赖 type 类型,最多它的一些反射/自省逻辑需要调用type。 object是一种类型,type是描述类型的类型。
我想这大概是是为了完成完全的面向对象,既然万物都是对象,那最源头的对象又是谁的实例?type和object很好地解决了这个问题:抓着自己的鞋带把自己提起来(bootstrap)。
python新手,说错请指正。 Python中一切皆对象,凡事对象都有类型。
从cpython/object.h at 2.7 · python/cpython · GitHub
>>> object.__class__
>>> type.__class__
也不是互为子类:
>>> object.__bases__
()
>>> type.__bases__
(,)
type和object都是type的实例,而type是object的子类。
__class__是这两个关系中更基本的一个。所有Python对象都有对应的class对象,而对一个Python的几乎所有操作,即使是访问对象属性o.a这么基本的,都是转交给其class对象执行。唯二的例外,是__class__和id,这两个操作的语义无法被class对象改变。在这方面,Python的可定制程度比绝大部分OOPL要高。
type是所有class对象的class,也称为metaclass。它决定了你直接操作class对象(而不是通过其实例)时的行为。例如:
要搞懂这个问题,首先要先把类、类型、对象这些概念全部舍掉,重构世界观。
首先,python里面一切皆是对象,包括type、object、所有class,全部都是对象,
那对象之间靠什么联系在一起呢?没错,靠的就是关系:
Python的世界里,对象之间一共有两种关系:
1、继承关系:
比如有class A和class B(A),再强调一下,A和B都是对象,
则对象B继承了对象A,或者说A是B的超类,
继承关系可以通过__base__属性得知,
如
两个是互为实例的关系,但不是互为子类的关系,只有type是object的子类,反之则不成立。大牛说两者是蛋生鸡鸡生蛋的关系,但我还是不明白,有懂的麻烦解释一下,希望不要给出外文的链接。python为什么设计出两个,去掉 一个行不行?
回复内容:
给别人讲解过很多次,但写成文字是第一次。试一试吧,自己主要也是看了这篇文章(Python Types and Objects)才懂的。object 和 type的关系很像鸡和蛋的关系,先有object还是先有type没法说,obejct和type是共生的关系,必须同时出现的。
在看下去之前,也要请先明白,在Python里面,所有的东西都是对象的概念。
在面向对象体系里面,存在两种关系:
- 父子关系,即继承关系,表现为子类继承于父类,如『蛇』类继承自『爬行动物』类,我们说『蛇是一种爬行动物』,英文说『snake is a kind of reptile』。在python里要查看一个类型的父类,使用它的__bases__属性可以查看。
- 类型实例关系,表现为某个类型的实例化,例如『萌萌是一条蛇』,英文说『萌萌 is an instance of snake』。在python里要查看一个实例的类型,使用它的__class__属性可以查看,或者使用type()函数查看。
这两种关系使用下面这张图简单示意,继承关系使用实线从子到父连接,类型实例关系使用虚线从实例到类型连接:
我们将使用一块白板来描述一下Python里面对象的关系,白板划分成三列:
先来看看type和object:
>>> object
>>> type
它们都是type的一个实例,表示它们都是类型对象。
在Python的世界中,object是父子关系的顶端,所有的数据类型的父类都是它;type是类型实例关系的顶端,所有对象都是它的实例的。它们两个的关系可以这样描述:
- object是一个type,object is and instance of type。即Object是type的一个实例。
>>> object.__class__
>>> object.__bases__ # object 无父类,因为它是链条顶端。
()
- type是一种object, type is kind of object。即Type是object的子类。
>>> type.__bases__
(
>>> type.__class__ # type的类型是自己
此时,白板上对象的关系如下图:
我们再引入list, dict, tuple 这些内置数据类型来看看:
>>> list.__bases__
(
>>> list.__class__
>>> dict.__bases__
(
>>> dict.__class__
>>> tuple.__class__
>>> tuple.__bases__
(
它们的父类都是object,类型都是type。
再实例化一个list看看:
>>> mylist = [1,2,3]
>>> mylist.__class__
>>> mylist.__bases__
Traceback (most recent call last):
File "
AttributeError: 'list' object has no attribute '__bases__'
实例化的list的类型是
把它们加到白板上去:
白板上的虚线表示源是目标的实例,实线表示源是目标的子类。即,左边的是右边的类型,而上面的是下面的父亲。
虚线是跨列产生关系,而实线只能在一列内产生关系。除了type和object两者外。
当我们自己去定个一个类及实例化它的时候,和上面的对象们又是什么关系呢?试一下:
>>> class C(object):
... pass
...
>>> C.__class__
>>> C.__bases__
(
实例化
>>> c = C()
>>> c.__class__
>>> c.__bases__
Traceback (most recent call last):
File "
AttributeError: 'C' object has no attribute '__bases__'
这个实例化的C类对象也是没有父类的属性的。
再更新一下白板:
白板上的第一列,目前只有type,我们先把这列的东西叫Type。
白板上的第二列,它们既是第三列的类型,又是第一列的实例,我们把这列的对象叫TypeObject。
白板上的第三列,它们是第二列类型的实例,而没有父类(__bases__)的,我们把它们叫Instance。
你以为事情就这样完了?不。。看见type孤零零在第一列其实不是那么舒服。。我们给它整几个玩伴看看。但要怎么整呢?要属于第一列的,必须是type的子类,那么我们只需要继承type来定义类就可以了:
>>> class M(type):
... pass
...
>>> M.__class__
>>> M.__bases__
(
>>>
嗯嗯,M类的类型和父类都是type。这个时候,我们可以把它归到第一列去。那么,要怎么样实例化M类型呢?实例化后它应该出现在那个列?嗯嗯,好吧,刚才你一不小心创建了一个元类,MetaClass!即类的类。如果你要实例化一个元类,那还是得定义一个类:
>>> class TM(object):
... __metaclass__ = M # 这样来指定元类。
...
...
>>> TM.__class__
>>> TM.__bases__
(
好了,现在TM这个类就是出现在第二列的。
再总结一下:
第一列,元类列,type是所有元类的父亲。我们可以通过继承type来创建元类。
第二列,TypeObject列,也称类列,object是所有类的父亲,大部份我们直接使用的数据类型都存在这个列的。
第三列,实例列,实例是对象关系链的末端,不能再被子类化和实例化。
到现在为止,Python类型的秘密已经说穿了,不一小心连元类也暴露了。哎。慢慢消化吧,信息量很大。
如果转述版看不懂,那么去啃一啃原文的吧:(Python Types and Objects)
=============更新=============
更新更新。。回答一下题主在问题后面说的为什么要有两个,而不是一个。
如果type和object只保留一个,那么一定是object。只有object 时,第一列将不复存在,只剩下二三列,第二列表示类型,第三列表示实例,这个和大部分静态语言的类型架构类似,如java 。
这样的架构将让python 失去一种很重要的动态特性--动态创建类型。本来,类(第二列的同学)在Python里面是一个对象(typeobject),对象是可以在运行时动态修改的,所以我们能在你定义一个类之后去修改他的行为或属性!拿掉第一列后,第二列变成了纯类型,写成怎样的,运行时行为就怎样。在这一点上,并不比静态语言有优势。
所以,以上! 那我就来补充个跟实现思路相关的传送门吧:先有Class还是先有Object? - RednaxelaFX 的回答
图对不对先不管。我们先来看看 type 和 object 分别是什么。
type 实际上是:
#define PyVarObject_HEAD_INIT(type, size) \
1, type, size,
PyTypeObject PyType_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
"type", /* tp_name */
sizeof(PyHeapTypeObject), /* tp_basicsize */
sizeof(PyMemberDef), /* tp_itemsize */
0, /* tp_base */
...
}
谢邀,object是type(object的类型是type),type也是object(type继承自object)>>> isinstance(object, type)
True
>>> isinstance(type, object)
True
这部分我当初是读MSDN里关于C Sharp的Object 和 type 的关系读懂的……你如果手边有Jeffery的《CLR via C#》 可以读一下。专门为了这个问题去买一本可能有点奢侈,不过如果你是 .net 程序员,我推荐你收一本。简单的说,很多运行时体系(不一定是针对某种语言)都提供在运行时获取类型信息的功能,那么获取出来的是什么东西呢?获取出来的是一个描述类型信息的对象。那么所有描述类型信息的对象,都是“类型”这个类型的实例。这个type类型不是类型本身,而是用于描述类型的对象实例,类型本身是一种抽象的信息,type类的实例对象是它具体的信息载体。既然type类型也是一种类型,那么它是公共根类型object的一个派生,也就是合情合理的设计了。
反过来,object 类型并不依赖 type 类型,最多它的一些反射/自省逻辑需要调用type。 object是一种类型,type是描述类型的类型。
- 所有对象都一定是某一个类的实例
- 在python中类也是对象,所有类都是type元类的实例
- type元类也是对象,它是它自己的实例,它的父类是object
- object是类,它是type的实例,object没有父类
我想这大概是是为了完成完全的面向对象,既然万物都是对象,那最源头的对象又是谁的实例?type和object很好地解决了这个问题:抓着自己的鞋带把自己提起来(bootstrap)。
python新手,说错请指正。 Python中一切皆对象,凡事对象都有类型。
从cpython/object.h at 2.7 · python/cpython · GitHub
/* PyObject_HEAD defines the initial segment of every PyObject. */
#define PyObject_HEAD \
_PyObject_HEAD_EXTRA \
Py_ssize_t ob_refcnt; \
struct _typeobject *ob_type;
既不是互为实例:>>> object.__class__
>>> type.__class__
也不是互为子类:
>>> object.__bases__
()
>>> type.__bases__
(
type和object都是type的实例,而type是object的子类。
__class__是这两个关系中更基本的一个。所有Python对象都有对应的class对象,而对一个Python的几乎所有操作,即使是访问对象属性o.a这么基本的,都是转交给其class对象执行。唯二的例外,是__class__和id,这两个操作的语义无法被class对象改变。在这方面,Python的可定制程度比绝大部分OOPL要高。
type是所有class对象的class,也称为metaclass。它决定了你直接操作class对象(而不是通过其实例)时的行为。例如:
class C(object):
a = 1
def f(self):
pass
c = C()
c.f() # 行为由C决定
C.a # 行为由type决定
之前读过一篇讨论这个问题文章,链接已经丢了。。。建议题主读一读《Ruby元编程》,这本书对类和对象有较清晰和深入的讨论,要求不高,Ruby和Python的对象模型非常相似,不懂Ruby也能读懂。要搞懂这个问题,首先要先把类、类型、对象这些概念全部舍掉,重构世界观。
首先,python里面一切皆是对象,包括type、object、所有class,全部都是对象,
那对象之间靠什么联系在一起呢?没错,靠的就是关系:
Python的世界里,对象之间一共有两种关系:
1、继承关系:
比如有class A和class B(A),再强调一下,A和B都是对象,
则对象B继承了对象A,或者说A是B的超类,
继承关系可以通过__base__属性得知,
如
相关文章
相关视频
专题推荐
-
独孤九贱-php全栈开发教程
全栈 170W+
主讲:Peter-Zhu 轻松幽默、简短易学,非常适合PHP学习入门
-
玉女心经-web前端开发教程
入门 80W+
主讲:灭绝师太 由浅入深、明快简洁,非常适合前端学习入门
-
天龙八部-实战开发教程
实战 120W+
主讲:西门大官人 思路清晰、严谨规范,适合有一定web编程基础学习
下一篇: Python之str操作详解
网友评论
文明上网理性发言,请遵守 新闻评论服务协议
我要评论