python 对象引用,可变性和垃圾回收

a = [1,2,3,4]
b = a

每个变量都有标识,类型和值.对象一旦创建,它的标识绝不会变;标识可以简单的理解为对象在内存中的地址.

  • 别名 ab 是别名指向 [1,2,3,4],如果a增加新的内容,b也会增加.
  • 相等性 b == atrue.==运算符比较连个对象的值(对象中保存的数据)
  • 标识 b is atrue,因为他们都指向 [1,2,3,4] 这个列表,is比较对象的标识

元组相对不可变性

  • 元组保存对象的引用,跟python的集合set一样,如果引用的元素是可变的,即便元组本身不可变,元素依然可变.即:元组的不可变形其实指tuple数据结构的物理内容(即保存的引用)不可变,与引用对象无关

默认做浅层复制

  • 浅层复制 : 1.复制了最外层容器,副本中的元素是源容器中元素的引用 2.他们的值相等,单两者指向不同的对象. 3.副本共享内部对象的引用
  • 浅层复制

    • 若所有元素都是不可变的,不存在任何问题,并节省了内存.
    • 如果存在可变的元素,如list会导致意想不到的问题.
l1 = [3,[66,55,44],(7,8,9)]
l2 = list(l1)
l1.append(100)  # 由于只复制了外层容器,这里仅有l1内容发生变化
l1[1].remove(55) # l1[1] 是一个list可变的元素,所有以l2[1]的元素也发生变化
l2[1] +=[33,22]
l2[2] += (10,11) # l2[2]是tuple,不可变的元素所有只有l2[2]发生变化.

深层复制,副本不共享内部对象的引用

函数的参数作为引用时

  • python中唯一支持的参数传递模式是共享传参 call by sharing
  • 共享传参:函数的各个形式参数获得实参中各个运用的副本,即是函数内部的形参是实参的别名
  • 影响:函数可能会修改作为参数传入的可变对象,但无法修改那些对象的标识

不要使用可变类型作为参数的默认值
可变参数作为默认值会导致:如果么有指定内容,会共用一个对象.所以通常使用Nono作为接收可变值得参数的默认值.

防御可变参数

  • 如果定义函数的接受可变参数,应该谨慎的考虑调用方是否期望修改传入的参数.

del和垃圾回收

  • 对象绝不会自行销毁;然而,无法得到对象时,可能会被当做垃圾处理.一个对象的引用数量为0的话会被销毁
    原文作者:Victorchi
    原文地址: https://segmentfault.com/a/1190000016257847
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞