因为要和别人讲理,所以把这部分代码看了看。
大概说一下我的理解。python广义上的垃圾回收是用两种互补的方式实现的:首先对于每一个对象,如果它的引用计数减到0,那么它的__del__会先被调用然后被回收;python里还有一个gcmodule,这个模块虽然叫gc,但其实只是处理循环引用的问题。注释中明确地说了这个gcmodule中不会发现引用计数为0的对象。这个模块中有分代的机制。
比较java/C#和python的垃圾收集(也许是内存管理)大概有两方面区别。python和java/C#第一个区别是垃圾回收的时机。python是一旦一个对象的引用计数减为0就把这个对象回收,这里实际上是延续了C/C++的思维方式(考虑new/delete)。而java/C#都是在内存紧张才会执行整个空间上的垃圾回收。这里python看上去的好处是__del__的调用时机很明确,但是如果深入观察就会发现其实不是这样,因为你没办法控制引用计数,一旦发生循环引用你依然没办法控制__del__调用的时机(根据源码__del__还是有可能根本不被调用)。我是很怀疑python在这里把可以一起做的事情拆散了,因为完全可以在gcmodule处理循环引用的时候一并处理引用计数为零的情况。
另外的区别就是对堆的使用方式。java在创建对象时用的是很简单的方法就是从前向后不断分配――很想栈所以很快,这样在垃圾收集时,显然必要地,会对回收后还在使用的内存进行压缩。而python(至少是CPython)是继承了C的malloc,我对malloc的机制不怎么熟悉,印象中应该是空闲块list的方式吧,可能不对。加之前面回收时机的问题,这就使得python很需要一个高效的pool。
以上两种综合的机制(立即回收+malloc vs. 必要时回收+像栈一样使用,实际上有点像C/C++ vs. java了)哪个效率更高肯定是根具体实现有关的,要看具体的数据结构和算法(回收算法,pool的实现)。不过如果是java/C#对比python,那么java/C#作为大厂商们的推崇,胜出应该必然的结果。