Python的內存管理是經過對象的引用計數器來實現的,對象的建立會將引用計數器加1,被引用一次則引用計數器就會加1,反之解除引用時,則引用計數器就會減1,當Python對象的引用計數器爲0的時候,則這個對象就會被回收和釋放。python
這種內存管理的方式是有必定的弊端的,一是它須要額外的空間維護引用計數,二是它不能解決對象的「循環引用」的問題,所以,也有不少語言好比Java並無採用該算法作來垃圾的回收機制。算法
Python代碼實例app
import sys def test_refcount(a): print("func a refcount: {}".format(sys.getrefcount(a))) if __name__ == '__main__': // 直接建立Python對象 a = 189987319 print("a refcount: {}".format(sys.getrefcount(a))) // 調用一次Python對象a,則引用計數器加1 b = a print("b, a refcount: {}".format(sys.getrefcount(a))) // 存入列表,字段,或者元組中,引用計數器都會加1 c = [a] print("c, a refcount: {}".format(sys.getrefcount(a))) // 使用函數調用的時候,傳參的時候引用計數器加1,調用的時候引用計數器也會加1,所以是加2 test_refcount(a) 結果: a refcount: 1 b, a refcount: 2 c, a refcount: 3 func a refcount: 5
void Py_INCREF(PyObject *o) Python對象引用計數器加1,該對象不能爲NULL,不然會報錯ide
void Py_XINCREF(PyObject *o) Python對象引用計數器加1,該對象能夠爲NULL,可是引用計數器未生效函數
void Py_DECREF(PyObject *o) Python對象的引用計數器減1,該對象不能爲NULL,不然會報錯ui
void Py_XDECREF(PyObject *o) Python對象引用計數器減1,該對象能夠爲NULL,可是引用計數器未生效code
void Py_CLEAR(PyObject *o) 直接將Python應用計數器清0orm
C代碼實例server
頭文件對象
// // Created by lanyulei on 18-9-9. // #ifndef PRINT_DEMO1_PYREFCOUNT_H #define PRINT_DEMO1_PYREFCOUNT_H #include <stdio.h> #include <stdlib.h> #include <string.h> #include <Python.h> void pyRefCount(); #endif //PRINT_DEMO1_PYREFCOUNT_H
源文件
// // Created by lanyulei on 18-9-9. // #include "pyRefCount.h" // Python對象的保留及釋放 void pyRefCount(){ PyObject* py_ival = Py_BuildValue("i", 56486); // 建立對象 printf("Py_BuildValue: py_ival refcount: %ld\n", Py_REFCNT(py_ival)); // 打印Python對象的引用計數器 Py_XINCREF(py_ival); // Python對象的引用計數器加1 printf("Py_BuildValue: py_ival refcount: %ld\n", Py_REFCNT(py_ival)); // 打印Python對象的引用計數器 Py_XDECREF(py_ival); // Python對象的引用計數器減1 printf("Py_BuildValue: py_ival refcount: %ld\n", Py_REFCNT(py_ival)); // 打印Python對象的引用計數器 Py_CLEAR(py_ival); // Python對象的引用計數器清0 printf("Py_BuildValue: py_ival refcount: %ld\n", Py_REFCNT(py_ival)); // 打印Python對象的引用計數器 }
main.cpp
#include "pyRefCount.h" int main() { // 初始化Python虛擬機 Py_Initialize(); // 判斷Python虛擬機是否成功 if (Py_IsInitialized() == 0){ printf("fal to initialize Python\n"); return -1; } printf("server start\n"); pyRefCount(); // 退出Python虛擬機 Py_Finalize(); return 0; }
Python虛擬機在運行的時候,import一個模塊的時候,若是這個模塊沒有被加載過,則Python虛擬機就會在執行程序的所在路徑搜索這個腳本,若是找到腳本文件就將它加載,若是沒有找到,就會從sys.path中的全部路徑去搜索,若是找到腳本文件就加載,反之則報錯。
Python下的sys.path
打印全部的sys.path下的路徑
>>> import sys >>> sys.path ['', 'C:\\WINDOWS\\SYSTEM32\\python27.zip', 'D:\\software\\Python2\\DLLs', 'D:\\software\\Python2\\lib', 'D:\\software\\Python2\\lib\\plat-win', 'D:\\software\\Python2\\lib\\lib-tk', 'D:\\software\\Python2', 'D:\\software\\Python2\\lib\\site-packages', 'D:\\software\\Python2\\Lib\\site-packages\\pytesser_v0.0.1']
將當前路徑加入到sys.path
>>> import os >>> import sys >>> sys.path.append(os.getcwd()) >>> sys.path ['', 'C:\\WINDOWS\\SYSTEM32\\python27.zip', 'D:\\software\\Python2\\DLLs', 'D:\\software\\Python2\\lib', 'D:\\software\\Python2\\lib\\plat-win', 'D:\\software\\Python2\\lib\\lib-tk', 'D:\\software\\Python2', 'D:\\software\\Python2\\lib\\site-packages', 'D:\\software\\Python2\\Lib\\site-packages\\pytesser_v0.0.1', 'C:\\WINDOWS\\system32']
C/C++初始化Python腳本路徑
頭文件
// // Created by win7 on 2018/9/10. // #ifndef INC_20180910_PYINIT_H #define INC_20180910_PYINIT_H #include <stdio.h> #include <stdlib.h> #include <string.h> #include <Python.h> bool initPython(); #endif //INC_20180910_PYINIT_H
源文件
// // Created by win7 on 2018/9/10. // #include "pyInit.h" bool initPython() { char scriptPath[128]; sprintf(scriptPath, "sys.path.append('%s')", "./script"); // 向Python註冊咱們的腳本路徑 PyRun_SimpleString("import sys"); PyRun_SimpleString(scriptPath); PyRun_SimpleString("print sys.path"); return true; }