Python integer objects implementation
2016-05-18 22:15
399 查看
http://www.laurentluce.com/posts/python-integer-objects-implementation/
This article describes how integer objects are managed by Python internally.
An integer object in Python is represented internally by the structure PyIntObject. Its value is an attribute of type long.
To avoid allocating a new integer object each time a new integer object is needed, Python allocates a block of free unused integer objects in advance.
The following structure is used by Python to allocate integer objects, also called PyIntObjects. Once this structure is initialized, the integer objects are ready to be used when new integer values are assigned to objects in a Python script. This structure is called “PyIntBlock” and is defined as:
When a block of integer objects is allocated by Python, the objects have no value assigned to them yet. We call them free integer objects ready to be used. A value will be assigned to the next free object when a new integer value is used in your program. No memory allocation will be required when a free integer object’s value is set so it will be fast.
The integer objects inside the block are linked together back to front using their internal pointer called ob_type. As noted in the source code, this is an abuse of this internal pointer so do not pay too much attention to the name.
Each block of integers contains the number of integer objects which can fit in a block of 1K bytes, about 40 PyIntObject objects on my 64-bit machine. When all the integer objects inside a block are used, a new block is allocated with a new list of integer objects available.
A singly-linked list is used to keep track of the integers blocks allocated. It is called “block_list” internally.
A specific structure is used to refer small integers and share them so access is fast. It is an array of 262 pointers to integer objects. Those integer objects are allocated during initialization in a block of integer objects we saw above. The small integers range is from -5 to 256. Many Python programs spend a lot of time using integers in that range so this is a smart decision.
The integer object representing the integer -5 is at the offset 0 inside the small integers array. The integers object representing -4 is at offset 1 …
What happens when an integer is defined in a Python script like this one?
When you execute the first line, the function PyInt_FromLong is called and its logic is the following:
With our example: integer 1 object is pointed by the small integers array at offset: 1+5 = 6. A pointer to this integer object will be returned and the variable “a” will be pointing to that integer object.
Let’s a look at a different example:
view source
print?
300 is not in the range of the small integers array so the next free integer object’s value is set to 300.
If you take a look at the file intobject.c in the Python 2.6 source code, you will see a long list of functions taking care of operations like addition, multiplication, conversion… The comparison function looks like this:
The value of an integer object is stored in its ob_ival attribute which is of type long. Each value is placed in a register to optimize access and the comparison is done between those 2 registers. -1 is returned if the integer object pointed by v is less than the one pointed by w. 1 is returned for the opposite and 0 is returned if they are equal.
That’s it for now. I hope you enjoyed the article. Please write a comment if you have any feedback.
Python integer objects implementation
May 15, 2011This article describes how integer objects are managed by Python internally.
An integer object in Python is represented internally by the structure PyIntObject. Its value is an attribute of type long.
1 | typedef struct { |
2 | PyObject_HEAD |
3 | long ob_ival; |
4 | } PyIntObject; |
The following structure is used by Python to allocate integer objects, also called PyIntObjects. Once this structure is initialized, the integer objects are ready to be used when new integer values are assigned to objects in a Python script. This structure is called “PyIntBlock” and is defined as:
1 | struct _intblock { |
2 | struct _intblock *next; |
3 | PyIntObject objects[N_INTOBJECTS]; |
4 | }; |
5 | typedef struct _intblock PyIntBlock; |
The integer objects inside the block are linked together back to front using their internal pointer called ob_type. As noted in the source code, this is an abuse of this internal pointer so do not pay too much attention to the name.
Each block of integers contains the number of integer objects which can fit in a block of 1K bytes, about 40 PyIntObject objects on my 64-bit machine. When all the integer objects inside a block are used, a new block is allocated with a new list of integer objects available.
A singly-linked list is used to keep track of the integers blocks allocated. It is called “block_list” internally.
A specific structure is used to refer small integers and share them so access is fast. It is an array of 262 pointers to integer objects. Those integer objects are allocated during initialization in a block of integer objects we saw above. The small integers range is from -5 to 256. Many Python programs spend a lot of time using integers in that range so this is a smart decision.
1 | #define NSMALLPOSINTS 257 |
2 | #define NSMALLNEGINTS 5 |
3 | static PyIntObject *small_ints[NSMALLNEGINTS + NSMALLPOSINTS]; |
The integer object representing the integer -5 is at the offset 0 inside the small integers array. The integers object representing -4 is at offset 1 …
What happens when an integer is defined in a Python script like this one?
1 | >>> a=1 |
2 | >>> a |
3 | 1 |
1 | if integer value in range -5,256: |
2 | return the integer object pointed by the small integers array at the |
3 | offset (value + 5). |
4 | else: |
5 | if no free integer object available: |
6 | allocate new block of integer objects |
7 | set value of the next free integer object in the current block |
8 | of integers. |
9 | return integer object |
Let’s a look at a different example:
view source
print?
1 | >>> a=300 |
2 | >>> a |
3 | 300 |
If you take a look at the file intobject.c in the Python 2.6 source code, you will see a long list of functions taking care of operations like addition, multiplication, conversion… The comparison function looks like this:
1 | static int |
2 | int_compare(PyIntObject *v, PyIntObject *w) |
3 | { |
4 | register long i = v->ob_ival; |
5 | register long j = w->ob_ival; |
6 | return (i < j) ? -1 : (i > j) ? 1 : 0; |
7 | } |
That’s it for now. I hope you enjoyed the article. Please write a comment if you have any feedback.
相关文章推荐
- 错误解决:error while loading shared libraries: libcurl.so.4: cannot open shared object file: No such file or directory
- sql-syscolumns,INFORMATION_SCHEMA.columns,sysobjects
- Js中Prototype、__proto__、Constructor、Object、Function关系介绍
- object-oriented second work
- mssql的object_id
- J2SE(十八)Object之Clone
- Objective-C ---NSArray NSDictionary(梳理整理)
- Programming with Objective-C(六)
- 摘抄的ObjectMapper用法
- request.getParameterMap() 转换为 Map<String, Object>
- Object类概述
- object-c中的-和+
- object-c中类的定义
- javascript dateObject.getYear()的历史遗留问题
- ObjectiveC基础-ivar是什么意思
- Objective-C 学习笔记
- 跟王老师学泛型(五): 自定义带泛型声明的方法
- IOS 开发 OC(Object_C)与前端页面JS(JavaScript)交互整理(一)
- 跟王老师学泛型(一)使用泛型
- Scriptable Object