python中的垃圾回收机制主要以引用计数为主要手段,辅以标记清除和分代回收机制。可以自动管理内存中的无效数据!在这篇文章中,带着这个问题继续阅读:你怎么知道一个对象是否可以被调用?查看内存地址。Python中的任何变量都有一个对应的内存引用,也就是内存地址。如果不是容器类型,那么就无法直接引用、赋值、内存地址。>>>a=1>>>b=1>>>id(a)140709385600544>>>id(b)140709385600544如果在内存中创建一个列表对象(容器),并引用该对象。那么b=[1,2]和c=a有什么区别呢?>>>a=[1,2]>>>b=[1,2]>>>id(a)1966828025736>>>id(b)1966828044488>>>c=a>>>id(c)1966828025736首先在内存1966828025736创建一个列表[1,2],然后定义一个名为a的变量。b=[1,2]会开辟一个新的内存地址,c=直接赋值直接引用[1,2]的内存地址。引用计数在一些代码中,如果有些变量存在但是没有用,会造成内存占用,所以称为垃圾,所以需要回收。引用计数也是最直观和最简单的垃圾收集技术之一。原理很简单。每个对象包含两个头信息,一个是类型标识符,标识对象的类型;另一个是计数器,它记录了当前指向该对象的引用数,表示这个对象存储在多少个变量名中。CPython使用引用计数来管理内存。在Python脚本中创建的所有实例都会有一个引用计数来记录有多少指针指向它。当引用计数仅为0时,内存会自动释放。Python中通过sys.getrefcount查看引用计数的方法,print(sys.getrefcount())注意调用getrefcount()函数会临时增加一次引用计数,结果比预期的多1。比如下面的例子,a的引用计数为3,因为有a,b,getrefcount三个地方作为参数传入,都引用了一个空列表。>>>importsys>>>a=[]>>>b=a>>>print(sys.getrefcount(a))3让我们看一些例子来增加或减少python对象的引用计数。importsysa=[]#两个引用,一个来自a,一个来自getrefcountprint(sys.getrefcount(a))deffunc(a):#四个引用,a,python的函数调用栈,函数参数,getrefcountprint(sys.getrefcount(a)))func(a)#两个引用,一个来自a,一个来自getrefcount,函数func调用不存在了print(sys.getrefcount(a))##########output##########242引用计数用于记录一个对象被引用的次数。每当创建或引用一个对象时,对该对象的引用数就会增加一个。当对对象的引用被销毁时,对对象的引用次数减一。当一个对象的引用数减少为零时,意味着程序中没有对象持有该对象的引用。换句话说,该对象将不会在以后的程序运行中再次使用。它也可以被释放。计数增减引用计数增加的场景如下:创建一个对象并赋值给一个变量,如:a='ABC'变量之间相互引用(相当于变量指向同一个对象),如:b=作为参数传递给函数的变量。例如:ref_method(a),将对象放入一个容器对象(列表、元组、字典)中。例如:c=[1,a,'abc']引用计数减少的场景:当一个变量离开作用域时,例如:当函数执行完成时,方法执行前后的引用计数仍然存在不变,因为方法执行完之后,对象的引用计数也会减少。如果在方法中打印,可以看到引用计数增加的效果。当对象的引用变量被销毁时,如dela或delb。注意,如果dela,去获取a的引用计数会直接报错。对象从容器对象中移除,如:c.remove(a)直接销毁整个容器,如:delc将对象的引用赋值给其他对象,即变量不指向previous对象,但是指向一个新的对象,在这种情况下,引用计数肯定会发生变化。(不包括两个对象的默认引用计数一致的场景)。importsysdefref_method(str):print(sys.getrefcount(str))print("我调用了{}".format(str))print('方法完成')defref_count():#引用计数增加的场景print('测试引用计数增加')a='A'print(sys.getrefcount(a))b=aprint(sys.getrefcount(a))ref_method(a)print(sys.getrefcount(a))c=[1,a,'abc']print(sys.getrefcount(a))#引用计数减少场景print('测试引用计数减少')delbprint(sys.getrefcount(a))c.remove(a)print(sys.getrefcount(a))delcprint(sys.getrefcount(a))a=783print(sys.getrefcount(a))if__name__=='__main__':ref_count()##########output##########测试引用计数增加78#77+177在函数中是随机的7981我调用了方法A执行了7980测试引用计数减少了7978784本文收录了GitHub,传送门~[2],里面大厂比较多面试完整考点,欢迎Star。
