小谈Python深浅拷贝及赋值

小谈Python深浅拷贝及赋值

a = [1, 2, "hello", ['Python', 'C++']]

浅拷贝(shallow copy)
浅拷贝
  • 浅拷贝会创建新的对象, 其内容非原对象本身的引用, 而是原对象内第一层对象的引用
  • 浅拷贝有三种形式: 切片操作、工厂函数和copy模块中的copy函数
    • 切片操作: b = a[:] 或者 b = [x for x in a]
    • 工厂函数: b = list(a)
    • copy函数: b = copy.copy(a)
  • 浅拷贝产生的列表b不再是列表a了, 使用is判断可以发现他们不是同一个对象, 使用id()查看, 它们指向的也不是同一片内存空间了。 但是当我们使用id(x) for x in aid(x) for x in b来查看a和b中的元素的地址时, 可以看出而这包含的元素地址是相同的。
  • 在这种情况下, 列表a和b是不同对象, 修改列表b理论上不会影响列表a。
注意
  • 要注意的是浅拷贝之所以称之为浅拷贝, 是它仅仅只拷贝了一层, 在列表a中嵌套的list, 如果我们修改它, 情况就不一样了。
  • 如: a[3].append('Java'), 再去查看列表b, 会发现列表b也发生了变化, 这是因为, 我们修改了嵌套的list, 修改外层元素, 会修改它的引用, 让它指向别的位置, 修改嵌套列表中的元素, 列表的地址不会发生变化, 指向的都是一个位置。
深拷贝(deep copy)
深拷贝
  • 深拷贝和浅拷贝对应, 深拷贝拷贝了对象的所有元素, 包括多次嵌套的元素. 因此, 它的时间和空间开销要高。
  • 同样对于列表a, 如果使用b = copy.deepcopy(a), 再修改列表b将不会影响到列表a, 即使嵌套的列表在更深的层次, 也不会产生任何影响, 因为深拷贝拷贝出来的对象根本就是一个全新的对象, 不再与原来的对象有任何关联。
拷贝的注意点
  • 对于非容器类型, 如数字,字符, 以及其他的"原子型", 没有拷贝一说, 产生的都是原对象的引用。
  • 如果元祖变量值包含原子类型对象, 即使采用了深拷贝, 也只能得到浅拷贝。
赋值
  • 在Python中, 对象的赋值就是简单的对象引用, 和C++不同, C++的赋值是调用赋值函数。
  • 如下:
    a = [1, 2, "hello", ['Python', 'C++']]
    b = a
  • 在上述情况下, a和b是一样的, 他们指向的是同一片内存, 但b不是a的别名, 是引用。
判断
  • 我们可以用b is a去判断, 返回True则表示他们地址相同, 内容也相同, 也可以使用id()函数来查看两个列表的地址是否相同。
  • 赋值操作(包括对象作为参数、返回值)不会开辟新的内存空间, 它只是复制了对象的引用. 也就是说除了b这个名字之外, 其没有其他的内存开销. 修改了a, 也就影响了b, 同理, 修改了b也就影响了a。
is 与 ==
is 与 ==
  • Python中对象包含的三个基本要素, 分别是id(身份标识符)type(数据类型)value(值)
  • is==都是对对象进行比较判断作用的,但对对象比较判断的内容并不相同。
    ==: 比较运算符
    is: 同一性运算符
区别
  • ==: 比较运算符, 在于判断两个对象的value(值)是否相等。
  • is: 同一性运算符, 这个运算符比较判断的是对象间的唯一身份标识,也就是id是否相同, 涉及深浅拷贝, 且只有容器类型涉及深拷贝, 当构造新的容器类型值时, 都相当于创建开辟新的内存空间, 而不是变量值内存地址的引用, 而数字,字符及其他"原子"型对象在被创建是都是对变量值内存地址的引用。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值