ホームページ バックエンド開発 Python チュートリアル 深入源码解析Python中的对象与类型

深入源码解析Python中的对象与类型

Jun 10, 2016 pm 03:07 PM
python 物体 タイプ

对象
对象, 在C语言是如何实现的?

Python中对象分为两类: 定长(int等), 非定长(list/dict等)

所有对象都有一些相同的东西, 源码中定义为PyObject和PyVarObject, 两个定义都有一个共同的头部定义PyObject_HEAD(其实PyVarObject有自己的头部定义PyObject_VAR_HEAD, 但其实际上用的也是PyObject_HEAD).

源码位置: Include/object.h

PyObject_HEAD
Python 内部, 每个对象拥有相同的头部.

定义

1

2

3

4

5

/* PyObject_HEAD defines the initial segment of every PyObject. */

#define PyObject_HEAD          \

  _PyObject_HEAD_EXTRA        \

  Py_ssize_t ob_refcnt;        \

  struct _typeobject *ob_type;

ログイン後にコピー

说明

1. _PyObject_HEAD_EXTRA
先忽略, 双向链表结构, 后面垃圾回收再说

2. Py_ssize_t ob_refcnt
Py_ssize_t在编译时确定, 整型
ob_refcnt, 引用计数, 跟Python的内存管理机制相关(基于引用计数的垃圾回收)

3. struct _typeobject *ob_type
*ob_type 指向类型对象的指针(指向_typeobject结构体)
决定了这个对象的类型!
PyObject
定义

1

2

3

typedef struct _object {

  PyObject_HEAD

} PyObject;

ログイン後にコピー

说明

1. 依赖关系
PyObject -> PyObject_HEAD
结构

20151211181600262.png (459×180)

PyVarObject
定义

1

2

3

4

5

6

7

typedef struct {

  PyObject_VAR_HEAD

} PyVarObject;

 

#define PyObject_VAR_HEAD        \

 PyObject_HEAD            \

 Py_ssize_t ob_size; /* Number of items in variable part */

ログイン後にコピー

说明

1. 依赖关系
PyVarObject -> PyObject_VAR_HEAD -> PyObject_HEAD

2.Py_ssize_t ob_size
ob_size, 变长对象容纳的元素个数
结构

20151211181633658.png (484×250)

代码关系

20151211181651468.png (740×385)

几个方法
跟对象相关的方法

#define Py_REFCNT(ob) (((PyObject*)(ob))->ob_refcnt)
读取引用计数

#define Py_TYPE(ob) (((PyObject*)(ob))->ob_type)
获取对象类型

#define Py_SIZE(ob) (((PyVarObject*)(ob))->ob_size)
读取元素个数(len)
跟引用计数相关的方法

Py_INCREF(op) 增加对象引用计数

Py_DECREF(op) 减少对象引用计数, 如果计数位0, 调用_Py_Dealloc

_Py_Dealloc(op) 调用对应类型的 tp_dealloc 方法(每种类型回收行为不一样的, 各种缓存池机制, 后面看)
其他
几个参数涉及

ob_refcnt 引用计数, 与内存管理/垃圾回收相关
ob_type 类型, 涉及Python的类型系统


类型
一个例子

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

>>> a = 1

>>> a

1

 

>>> type(a)

<type 'int'>

 

#等价的两个

>>> type(type(a))

<type 'type'>

>>> type(int)

<type 'type'>

 

#还是等价的两个

>>> type(type(type(a)))

<type 'type'>

>>> type(type(int))

<type 'type'>

ログイン後にコピー

我们反向推导一个int对象是怎么生成的.

1. 首先, 定义一种类型叫PyTypeObject
代码位置 Include/object.h

定义

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

typedef struct _typeobject {

 

 /* MARK: base, 注意, 是个变长对象*/

 PyObject_VAR_HEAD

 const char *tp_name; /* For printing, in format "<module>.<name>" */ //类型名

 Py_ssize_t tp_basicsize, tp_itemsize; /* For allocation */ // 创建该类型对象时分配的内存空间大小

 

 

 // 一堆方法定义, 函数和指针

 /* Methods to implement standard operations */

 printfunc tp_print;

 hashfunc tp_hash;

 

 /* Method suites for standard classes */

 PyNumberMethods *tp_as_number;  // 数值对象操作

 PySequenceMethods *tp_as_sequence; // 序列对象操作

 PyMappingMethods *tp_as_mapping; // 字典对象操作

 

 // 一堆属性定义

 ....

 

} PyTypeObject;

ログイン後にコピー

说明

1. PyObject_VAR_HEAD
变长对象

2. const char *tp_name
tp_name, 类型名字符串数组
所有Type都是PyTypeObject的"实例": PyType_Type/PyInt_Type

2. 然后, 用PyTypeObject初始化得到一个对象PyType_Type
代码位置 Objects/typeobject.c

定义

1

2

3

4

5

6

7

8

9

10

11

PyTypeObject PyType_Type = {

 PyVarObject_HEAD_INIT(&PyType_Type, 0)

 "type",                   /* tp_name */

 sizeof(PyHeapTypeObject),          /* tp_basicsize */

 sizeof(PyMemberDef),            /* tp_itemsize */

 (destructor)type_dealloc,          /* tp_dealloc */

 

 // type对象的方法和属性初始化值

 .....

 

};

ログイン後にコピー

说明

1. tp_name
类型名, 这里是"type"

2. PyVarObject_HEAD_INIT(&PyType_Type, 0)
PyVarObject_HEAD_INIT, 这个方法在 Include/object.h中,
等价于
ob_refcnt = 1
*ob_type = &PyType_Type
ob_size = 0

即, PyType_Type的类型是其本身!
结构

第一张图, 箭头表示实例化(google doc用不是很熟找不到对应类型的箭头)

20151211181832844.png (510×277)

第二张图, 箭头表示指向

20151211181846535.png (484×250)

使用

1

2

3

4

5

6

7

# 1. int 的 类型 是`type`

>>> type(int)

<type 'type'>

 

# 2. type 的类型 还是`type`, 对应上面说明第二点

>>> type(type(int))

<type 'type'>

ログイン後にコピー

注意: 无论任何时候, ob_type指向的是 PyTypeObject的实例: PyType_Type/PyInt_Type...

3. 再然后, 定义具体的类型, 这里以PyInt_Type为例子
代码位置 Objects/intobject.c

定义

1

2

3

4

5

6

7

8

9

10

11

12

PyTypeObject PyInt_Type = {

 PyVarObject_HEAD_INIT(&PyType_Type, 0)

 "int",

 sizeof(PyIntObject),

 0,

 

 // int类型的相关方法和属性值

 ....

 

 (hashfunc)int_hash,             /* tp_hash */

 

};

ログイン後にコピー

说明

1. "int"
PyInt_Type的类型名是int

2.PyVarObject_HEAD_INIT(&PyType_Type, 0)
PyInt_Type的

1

*ob_type = &PyType_Type

ログイン後にコピー

结构

20151211181940069.png (1083×570)

使用

1

2

3

4

5

>>> type(1)

<type 'int'>

 

>>> type(type(1))

<type 'type'>

ログイン後にコピー

4. 最后, 生成一个整数对象int
代码位置 Include/intobject.h

定义

1

2

3

4

typedef struct {

  PyObject_HEAD

  long ob_ival;

} PyIntObject;

ログイン後にコピー

结构

20151211182004246.png (1768×832)

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

Video Face Swap

Video Face Swap

完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

PHPおよびPython:さまざまなパラダイムが説明されています PHPおよびPython:さまざまなパラダイムが説明されています Apr 18, 2025 am 12:26 AM

PHPは主に手順プログラミングですが、オブジェクト指向プログラミング(OOP)もサポートしています。 Pythonは、OOP、機能、手続き上のプログラミングなど、さまざまなパラダイムをサポートしています。 PHPはWeb開発に適しており、Pythonはデータ分析や機械学習などのさまざまなアプリケーションに適しています。

PHPとPythonの選択:ガイド PHPとPythonの選択:ガイド Apr 18, 2025 am 12:24 AM

PHPはWeb開発と迅速なプロトタイピングに適しており、Pythonはデータサイエンスと機械学習に適しています。 1.PHPは、単純な構文と迅速な開発に適した動的なWeb開発に使用されます。 2。Pythonには簡潔な構文があり、複数のフィールドに適しており、強力なライブラリエコシステムがあります。

Sublime Code Pythonを実行する方法 Sublime Code Pythonを実行する方法 Apr 16, 2025 am 08:48 AM

PythonコードをSublimeテキストで実行するには、最初にPythonプラグインをインストールし、次に.pyファイルを作成してコードを書き込み、Ctrl Bを押してコードを実行する必要があります。コードを実行すると、出力がコンソールに表示されます。

PHPとPython:彼らの歴史を深く掘り下げます PHPとPython:彼らの歴史を深く掘り下げます Apr 18, 2025 am 12:25 AM

PHPは1994年に発信され、Rasmuslerdorfによって開発されました。もともとはウェブサイトの訪問者を追跡するために使用され、サーバー側のスクリプト言語に徐々に進化し、Web開発で広く使用されていました。 Pythonは、1980年代後半にGuidovan Rossumによって開発され、1991年に最初にリリースされました。コードの読みやすさとシンプルさを強調し、科学的コンピューティング、データ分析、その他の分野に適しています。

Python vs. JavaScript:学習曲線と使いやすさ Python vs. JavaScript:学習曲線と使いやすさ Apr 16, 2025 am 12:12 AM

Pythonは、スムーズな学習曲線と簡潔な構文を備えた初心者により適しています。 JavaScriptは、急な学習曲線と柔軟な構文を備えたフロントエンド開発に適しています。 1。Python構文は直感的で、データサイエンスやバックエンド開発に適しています。 2。JavaScriptは柔軟で、フロントエンドおよびサーバー側のプログラミングで広く使用されています。

Golang vs. Python:パフォーマンスとスケーラビリティ Golang vs. Python:パフォーマンスとスケーラビリティ Apr 19, 2025 am 12:18 AM

Golangは、パフォーマンスとスケーラビリティの点でPythonよりも優れています。 1)Golangのコンピレーションタイプの特性と効率的な並行性モデルにより、高い並行性シナリオでうまく機能します。 2)Pythonは解釈された言語として、ゆっくりと実行されますが、Cythonなどのツールを介してパフォーマンスを最適化できます。

vscodeでコードを書く場所 vscodeでコードを書く場所 Apr 15, 2025 pm 09:54 PM

Visual Studioコード(VSCODE)でコードを作成するのはシンプルで使いやすいです。 VSCODEをインストールし、プロジェクトの作成、言語の選択、ファイルの作成、コードの書き込み、保存して実行します。 VSCODEの利点には、クロスプラットフォーム、フリーおよびオープンソース、強力な機能、リッチエクステンション、軽量で高速が含まれます。

メモ帳でPythonを実行する方法 メモ帳でPythonを実行する方法 Apr 16, 2025 pm 07:33 PM

メモ帳でPythonコードを実行するには、Python実行可能ファイルとNPPEXECプラグインをインストールする必要があります。 Pythonをインストールしてパスを追加した後、nppexecプラグインでコマンド「python」とパラメーター "{current_directory} {file_name}"を構成して、メモ帳のショートカットキー「F6」を介してPythonコードを実行します。

See all articles