Python 中一切都是对象,那如果类是对象,那(什么)是类呢?

2018-09-06 22:18:35 +08:00
 mainlong

目前只能理解,数据类型是类,如 int 类,str 类等。

5186 次点击
所在节点    Python
29 条回复
lxy42
2018-09-07 09:43:38 +08:00
@fy #14 PyTypeObject 可以理解为元类吧。
gansteed
2018-09-07 10:04:40 +08:00
《 Python 源码剖析》这本书可以看一下。此外可以了解一下 `metaclass` 这个概念。type 就是 metaclass。metaclass 是 class 的 class。class 是 metaclass 的实例。例如 str, list, int 是 type 的实例。

class MyClass:
pass

这个 MyClass 默认继承 object,object 也是 type 的实例。my_instance = MyClass(),这里,MyClass 是 class。my_instance 是 MyClass 这个 class 实例化的结果。

晕了么?😁

参考资料:

- 《 Python 源码剖析》: https://book.douban.com/subject/3117898/
- "新式类": https://www.python.org/doc/newstyle/
glacer
2018-09-07 10:17:02 +08:00
在 Python 中,类是一种抽象的理念,在源码并不存在某个 class 的定义,因为类这个抽象理念在 Python 运行时中被实例化,Python 依靠运行时中的类实例来生成自己的对象实例,而不需要在代码中定义类的实现然后编译后在运行时载入内存。在 Python 的底层实现中,如 CPython,就对各个类的实现做了定位,比如 PyIntType,它在 Python 中对应的就是 int 类型,而各种类型实例对应 C 中的实现就是 PyIntobject。
xpresslink
2018-09-07 11:37:07 +08:00
Python 中所有东西都是对象,比较特殊的是:object 和 type 是 python 中的两个源对象,它们是互相依赖对方来定义,不能分割来说,
就如同讨论“先有鸡还是现有蛋”,一样让人蛋疼。

先介绍有两个黑魔法在后面要用到:
obj.__bases__ 指这个对象的父类,就是说从谁继承来的。
obj.__class__ 指这个对象的类型,类的类型是 type

Python 的面向对象系统有两条线索。

1.继承关系也就是父类和子类的关系( the subclass-superclass relationship ),以 object 为起点;

所有对象的父类是 object,因此 object 是没有父类的。
>>> object.__bases__
()

type 也是 object 的子类
>>> issubclass(type, object)
True
>>> type.__bases__
(<class 'object'>,)

2.类型和实例之间的关系( the type-instance relationship ),以 type 为起点。

type 是自身的实例,或说 type (对象 object )的 class (类型 type )是 type
>>> isinstance(type, type)
True

>>> type(type)
<class 'type'>

>>> type.__class__
<class 'type'>

就连 object 都是 type 的实例
>>> isinstance(type, object)
True


总结一下:
type 是一个比较特殊的类,这里引出另一概念元类,普通类实例化出来一个对象,但是元类实例化出来的是一个类,
int、float、str、boolean、tuple、dict、set 等内置的数据类型其实也就是内置的类都是 type 实例。

>>> isinstance(int, type)
True

>>> int.__class__
<class 'type'>
>>>


object 是所有对象(包括类对象)的父类,int、float、str、boolean、tuple、dict、set 内置类都是 object 子类。
>>> int.__bases__
(<class 'object'>,)

>>> isinstance(int, object)
True
PythonAnswer
2018-09-07 12:10:55 +08:00
楼上总结的很好。

但我总觉得 type 更早一些。谁来讲讲旧式类?当时 object 还没有强制使用。
SimbaPeng
2018-09-07 13:44:41 +08:00
Python 中只有 2 种对象,类和非类
HelloAmadeus
2018-09-07 21:14:02 +08:00
看点 python 源码实现就对"一切都是对象" 这种模糊的描述更清晰了. 举一个简单的例子两个 int 相加, 伪代码如下:

PyObject * Interger_Add(PyObject* left, PyObject* right) {
PyIntObject* int_left = (PyIntObject*) left;
PyIntObject* int_right = (PyIntObject*) left;
PyIntObject* int_new = (PyIntObject*) Py_GC_MALLOC(&PyIntObject);



}
HelloAmadeus
2018-09-07 21:49:22 +08:00
看点 python 源码实现就对"一切都是对象" 这种模糊的描述更清晰了. 举一个简单的例子如两个 int 相加, 伪代码如下:

PyObject * Interger_Add(PyObject* left, PyObject* right) {

PyIntObject* int_left = (PyIntObject*) left;
PyIntObject* int_right = (PyIntObject*) left;
PyIntObject* int_new = (PyIntObject*) Py_GC_MALLOC(&PyIntObject); # 在 malloc 之后做一些如添加引用计数等工作

int_new->ob_data = int_left->ob_data + int_right->ob_data; # ob_data 为 c long 类型
return (PyObject*) int_new;
}

你看, 一个 两个 int 型相加, 参数传进来的是 PyObject , 返回的是 PyObject. 一切都是对象是不是更好理解了.
还有 Python 的 module 是怎么也是对象. 也有类似这样的函数, PyObjcet* model_reload(PyObject* module);
你看重载 module, 参数传进来的都是 PyObject, 返回的也是 PyObject, 一切都是对象是不是更清晰了?

如果不从 Python 源码来理解的话, 你就要区分 object 这个关键词 python 与 c++和 java 中的区别, object 在 c++和 java 中的概念更像是 python 中 实例(instance) 的概念.

在面向对象编程概念里, 类是抽象数据和与这些抽象数据相关操作的集合, 对象是类的实例, 也就是具体数据和构建在这些具体数据上的集合. 这个概念与 python 中一切都是对象是完全不在一个层面上的比较.

面向对象是一种抽象, 他与语言是无关的, 任何语言都能实现面向对象中的至少一部分想法. 而"一切都是对象" 这句话描述的不是抽象, 而是具体的实现.

python 通过 PyObject 实现了面向对象这个抽象的思想. 所以在一些地方借鉴了思想的关键字. 如 class, object. 但是这些词并不是严格对应面向对象的概念, 因为 python 是多范式的编程语言.

所以把"一切都是对象"中的对象和面向对象编程中的对象 这两个对象区分开, 才能理解 python 中一切都是对象, 这个概念.

P.S. v2 的编辑器真是垃圾.
fy
2018-09-08 15:09:05 +08:00
@lxy42 #21 但 CPython 实现上并没有说 Type 这个 class 比其他 class 高一档或者有很多的特殊之处。metaclass 这个概念其实更多的是一种 class hack 或者是 injection

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/486928

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX