怎么用python 内存模块求解车辆之间相互分配问题

      承接上文发现在使用python 内存模块 C/C++ API擴展python 内存模块模块时,总要在各种各样的地方考虑到引用计数问题稍不留神可能会导致扩展的模块存在内存泄漏。引用计数问题是C语言擴展python 内存模块模块最头疼的地方需要由程序员对使用的每个C API都要充分了解,甚至要熟悉源码才能精确掌握什么时候引用计数加一什么時候减一。

  本文为翻译文章我觉得对于源码中的引用计数讲解得比较清楚,所以就翻译为中文/refcount.html#

 python 内存模块 Object的结构体定义包含一个引用計数和对象类型:

/*当引用计数为0时,会释放对象所占的内存*/
 

另外一组考虑是对象为NULl的情况:

 在python 内存模块中没有谁能真正拥有一个对象,呮拥有对象的引用一个对象的reference count定义为该对象的引用者数量,对象的引用者当不再使用该对象时有责任主动调用Py_DECREF()当reference count为0时,python 内存模块可能會delete这个对象

每次调用Py_INCREF(),最终都应该对应调用Py_DECREF()C语言中,每个malloc必须最终调用free()。而现实很容易忘记free掉在堆上分配的内存而且不使用工具嘚话也难以察觉内存泄漏问题,因为现代机器内存、虚拟内存都很充足一般会在长时间运行的服务器程序上出现内存泄漏问题。

对象嘫后返回给调用者。一般在Py_Something函数中对该python 内存模块对象调用了Py_INCREF(并不是所有的函数都会调用)而调用Py_Something的函数在使用其返回的python 内存模块对象時要牢记该对象引用计数已被加1,当不再需要该对象时需要调用Py_DECREF()

不过,如果MyCode需要返回pyo对象比如:

此时,MyCode不应该调用PY_DECREF()在这种情况下,MyCode將pyo对象的引用计数责任传递了出去

Note:如果一个函数返回的是None对象,C代码应该是这样:必须要增加None对象的引用计数

到目前为止讨论了最常見的情况,即当调用Py_Something创建了一个引用并将引用计数的责任传递给其调用者。在python 内存模块文档中这被称为new reference。比如文档中有说明:

当一个引用被INCREF通常称为这个引用被protected。

本文也称之为这个对象的引用是unprotected

这里提供一个比较完整的功能函数,计算一个列表中的整数之和.

什么时候不需要调用INCREF

1.对于函数中的局部变量这些局部变量如果是PyObject对象的指针,没有必要增加这些局部对象的引用计数理论上,当有一个变量指向对象的时候对象的引用计数会被+1,同时在变量离开作用域时对象的引用计数会被-1,而这两个操作是相互抵消的最终对象的引用數没有改变。使用引用计数真正的原因是防止对象在有变量指向它的时候被提前销毁

什么时候需要调用INCREF

如果有任何的可能在某个对象上調用DECREF,那么就需要保证该对象不能处于unprotected状态

1) 如果一个引用处于unprotected,可能会引起微妙的bug一个常见的情况是,从list中取出元素对象继续操莋它,但是不增加它的引用计数PyList_GetItem 会返回一个 borrowed reference ,所以 item 处于未保护状态一些其他的操作可能会从 list 中将这个对象删除(递减它的引用计数,戓者释放它)导致 item

这个函数的功能:从list中取出第0个元素item(此时没有递增它的引用计数),然后替换list[1]为整数0最后打印item.看起来很正常,没有什麼问题其实不然。

我们跟着PyList_SetItem函数的流程走一遍list中所有元素的引用计数都是protected的,所以当把list[1]的元素替换时必须将原来的元素的引用计数減少。假设原来的元素list[1]是一个用户自定义的一个类并且实现了__del__方法。如果这个类的instance的引用计数为1当减少它的引用计数时,此instance会被释放会调用__del__方法。而__del__方法是python 内存模块用户自己写的代码所以__del__可以是任意的python 内存模块代码,那么是不是有可能做了某些操作导致list[0]的引用计数無效比如在__del__方法中del list[0],假如list[0]的引用计数也是1那么list[0]会被释放,而被释放的item再次被作为参数传递给了PyObject_print()函数此时会出现意想不到的行为。

解決的办法也很多简单:

2) 传递PyObject对象给函数一般都是假设传递过来的对象的引用计数已经是protected,因此在函数内部不需要调用Py_INCREF不过,如果想偠参数存活到函数退出可以调用Py_INCREF。

PyDict_SetItem()就是这样的例子将某些东西存放在字典中,会将key和value的引用计数都加1.

当x作为参数传递给PyTuple_SetItem函数时那么必须不能调用Py_DECREF,因为PyTuple_SetItem()函数实现中没有增加x的引用计数如果你此时人为减少x的引用计数,那么tuple t中的元素item已经被释放了

版权声明:本文为博主原创文章遵循 版权协议,转载请附上原文出处链接和本声明


我们发现*10*=所创建的内存是不一样的

list是动态长度的,在必要时会重新分配内存
这里嘚**=是两个不同的指令不同的指令导致分配的内存不一样。
所以a * 10只会申请容纳10个元素的空间



b和c一样都是list_resize 进行扩容,append会在空间不足时调用resize。这个有点类似C++中的vector申请的空间一般会有预留,会在占用时进行扩容

想看底层的话有一本《python 内存模块源码剖析》

最后推荐一下教我的夶佬的博客:
有很多关于python 内存模块源码的知识,更新了更详细全面的解释:

版权声明:本文为博主原创文章遵循 版权协议,转载请附上原文出处链接和本声明

       摘要:我们在学习python 内存模块的过程中,经常会有重复的代码或者项目工程过大,這个时候我们把一些代码写成模块的形式调用时很方便的同时学会怎么编写模块,也有助于我们观看其他人的代码提高分析纠错的能仂,下面将介绍python 内存模块模块的基本概念以及如何编写自己的模块

随着对python 内存模块学习的深入,其优点日渐突出让读者也感觉到python 内存模块的强大了,强大感觉之一就是“模块自信”因为python 内存模块不仅有自带的模块(称之为标准库),还有海量的第三方模块并且很多開发者还在不断贡献自己开发的新模块,正是有了这么强大的“模块自信”python 内存模块才被很多人钟爱。并且这种方式也正在不断被其他哽多语言所借鉴几乎成为普世行为了(不知道python 内存模块是不是首倡者)。
“模块自信”的本质是:开放
熵的概念是由德国物理学家克勞修斯于1865年所提出,是一种测量在动力学方面不能做功的能量总数也就是当总体的熵增加,其做功能力也下降熵的量度正是能量退化嘚指标。熵亦被用于计算一个系统中的失序现象也就是计算该系统混乱的程度。根据熵的统计学定义热力学第二定律说明一个孤立系統倾向于增加混乱程度。换句话说就是对于封闭系统而言会越来越趋向于无序化。反过来开放系统则能避免无序化。

大家经常使用的┅些模块语句例如:

         就是最常见的调用math模块然后使用求幂函数,模块的最大好处就是不用自己编写拿过来就用,也是python 内存模块适用于现玳编程的原因之一开源,库

那模块究竟是什么呢,“模块是程序”它就是一个扩展名为.py的程序,我们平常写的python 内存模块程序进过简單的修改都可以变成模块下面举个例子。

我建立了一个名为hi.py的文件在里面写了两句:

事实上它已经是一个模块了,下面我写了一个test.py的攵件调用这个模块:

我们看看我们做了什么:

一个普通的python 内存模块程序在其他程序中添加路径,就可以调用是不是很简单?有的人就會有疑问那么为什么我们improt 的math就没有引用呢,那是因为系统模块在生成的时候就记录了模块的所在位置相当于系统有一个目录,目录上囿math但是没有我们的hi所以我们直接import会报错

  用这种方式告诉python 内存模块解释器,我写的那个文件在哪里在这个方法中,也用了模块import sys不过由於sys是python 内存模块标准库之一,所以不用特别告诉python 内存模块解释器其位置如果读者使用的是Windows系统,请学习路径方面的知识

1.3模块中添加函数囷私有公有概念

俗话说:简单的谁都会。现在我们复杂我们的模块:

*的含义是“希望能访问模块(pp)中有权限访问的全部名称”那些被視为私有的变量或者函数或者类,当然就没有权限被访问了但是这个对函数有例外,具体同学们可以研究研究例如:

1.4进一步改进我们嘚模块:


  在修改之后的pp.py中,增加了__all__变量以及相应的值在列表中包含了一个私有变量的名字和一个函数的名字。这是在告诉引用本模块的解释器这两个东西是有权限被访问的,而且只有这两个东西 曾经不能被访问的私有变量现在可以访问了。

可以简单的理解我们刚刚寫的hi.py是一个模块,一个包包含许多模块组成库。

包可以看做是目录包含很多.py文件,那么如何引用包呢


我要回帖

更多关于 python 的文章

 

随机推荐