(六)对象引用、可变性和垃圾回收

本节主要说明,对象与对象名称之间的区别。

一、变量不是盒子,而是标签

  如图。在赋值语句中,y=A()中,先创建对象A,然后将左边的变量绑定到对象上。变量只不过是标注,因此无法阻止为对象贴上多个标签(别名)

二、标识、相等性和别名

  1、对象一旦创建,标识就不会改变,标识可理解为对象在内存中的地址,is运算符比较两个对象的标识符,id返回对象标识符的整数表示。

  别名

 

  标识

  2、==和is

  ==比较两个对象的值(对象中保存的数据),is比较对象的标识。

   3、元组的相对不可变性

   元组的值会随着引用的可变对象的变化而变,不可变的是元素的标识

  

 四、浅复制

   1、默认做浅复制

      浅复制只复制了最外层的容器,副本中的元素是源容器中元素的引用。当元素都是不可变的,可以节省内存,当元素中有可变对象时,则容易出错。

  2、为任意对象做深复制和浅复制

   使用copy模块的copy和deepcopy

  

五、函数的参数作为引用

  1、python支持的参数传递是共享传参:各个形参获得实参中各个引用的副本,函数内部的形参是实参的别名。

 

  2、不要使用可变类型作为参数的默认值

    默认值在函数定义时计算(通常在加载模块时),因此默认值成了函数对象的属性。

 

  3、防御可变参数

   在类中,直接把参数赋值给实例变量,会为参数对象创建别名;如果不想因为类内的改变,去修改参数的值,则创建副本。

   

 

六、del和垃圾回收  

  del删除名称,不会删除对象,但此操作可能会导致对象不可获取,导致对象被删除。

  在CPython中,垃圾回收主要使用算法是引用计数。每个对象会统计有多少个引用指向自己,当引用计数归零时,对象立即被销毁。

  

 

七、弱引用

  没看明白,挖坑。。。。

总结

  1、变量保存的是引用,简单的赋值不能创建副本;

  2、对+=,*=所做的增量赋值来说,如果左边的变量绑定的是不可变对象,则会创建新对象,反之就地修改;

  3、为现有的变量赋予新值,不会修改之前绑定的变量(重新绑定):如果变量是之前对象的最后一个引用,对象会被当作垃圾回收;

  4、函数的参数以别名的形式传递,因此函数可能会修改通过参数传递的可变对象。在本地创建副本、传入不可变对象可以避免;

  5、使用可变类型作为默认参数有危险,如果就地修改了参数,默认值也就变了,这会影响以后默认值的调用;

  6、对象的引用计数归零后,对象会被立即销毁。

 

posted @ 2018-11-07 14:36  牧马人夏峥  阅读(177)  评论(0编辑  收藏  举报