# 对象和比较及深浅拷贝

# 对象的比较-'==' VS 'is'

  • 等于(==)和 is 是 Python 中对象比较常用的两种方式。

  • '=='操作符比较对象之间的值是否相等,调用的是对象__eq__函数

  • 'is'操作符比较对象的身份标识是否相等,即它们是否是同一个对象,是否指向同一个内存地址

    • 每个对象的身份标识可以通过id(object)获得
    • 对于[-5,256]的整数,is比较为True,因为Python内部会对-5到256的整形维持一个数组,起缓存作用,当试图创建这个范围内的整形数字时会返回这个数组中相对应的引用,而不是重新开辟一块的新的内存空间
  • 比较操作符'is'的速度效率,通常要优于'=='。因为'is'操作符不能被重载,这样,Python 就不需要去寻找,程序中是否有其他地方重载了比较操作符

# 对象的拷贝-浅拷贝和深度拷贝

  • 浅拷贝,是指重新分配一块内存,创建一个新的对象,里面的元素是原对象中子对象的引用

    • 一般有数据类型本身的构造器和切片操作
    • Python 中提供函数 copy.copy(),适用于任何数据类型实现浅拷贝
    • 注意对于元组使用构造器或切片操作不会创建浅拷贝而是返回一个指向相同元组的引用
    • 子对象可变则浅拷贝过去的也会变化(内容变了但对象没变)
  • 深度拷贝,是指重新分配一块内存,创建一个新的对象,并且将原对象中的元素,以递归的方式,通过创建新的子对象拷贝到新对象中。因此,新对象和原对象没有任何关联。

    • Python 中提供函数 copy.deepcopy(),适用于任何数据类型实现深度拷贝
    • 深度拷贝中会维护一个字典,记录已经拷贝的对象及其 ID,来提高效率并防止无限递归的发生。
# 浅拷贝
# 子对象的引用
l1 = [[1, 2], (30, 40)]
l2 = list(l1)
l1.append(100)
l1[0].append(3)

l1
[[1, 2, 3], (30, 40), 100]

l2
[[1, 2, 3], (30, 40)]

# 深拷贝
import copy
l1 = [[1, 2], (30, 40)]
l2 = copy.deepcopy(l1)
l1.append(100)
l1[0].append(3)

l1
[[1, 2, 3], (30, 40), 100]

l2 
[[1, 2], (30, 40)]