python深拷贝浅拷贝


python中的参数传递既不是值传递,也不是引用传递,而是赋值传递,或者说叫对象的引用传递,不是指向一个具体的内存地址,而是指向一个具体的对象

  • 对象是可变的,当其改变时,所有指向这个对象的变量都会改变
  • 如果对象不变,简单的赋值只能改变其中一个变量的值,其余变量不受影响

== 和 is

1.==是值得比较,is是id的比较,is的速度往往优于==(is的操作符无法重载,只是简单地获取id进行比较,而==操作符则会递归地遍历对象的所有值),被赋值的变量与赋值的变量id相等

2.创建一个-5到256范围内的整形数字时,python会从这个数组中返回相对应的引用,python都会从数组中返回相对引用,而不是开辟一个新的内存空间python

浅拷贝

1.浅拷贝对于完全不可变类型,不会拷贝仅仅只会指向,例如

import copy

# 可变对象,浅拷贝生效
a = [1, 2, 3]
b = copy.copy(a)
print(a is b)  # False

# 不可变对象,浅拷贝不生效,仅仅指向
a = (1, 2, 3)
b = copy.copy(a)
print(a is b)  # True

2.浅拷贝对象对于可变对象类型,只对顶层进行拷贝,如果有多层中有可变对象类型则只是引用,及里面的元素是原对象中子对象的引用

import copy

# 可变对象,可变对象[1, 2, 3]和不可变对象(1, 2, 3)
a = {"a": [1, 2, 3], "b": (1, 2, 3)}
b = copy.copy(a)
b["c"] = 100
print(a)  # {'a': [1, 2, 3], 'b': (1, 2, 3)}
print(b)  # {'a': [1, 2, 3], 'b': (1, 2, 3), 'c': 100}
b["a"].append(4)
print(a)  # {'a': [1, 2, 3, 4], 'b': (1, 2, 3)}
print(b)  # {'a': [1, 2, 3, 4], 'b': (1, 2, 3), 'c': 100}
b["b"] += (4, 5)
print(a)  # {'a': [1, 2, 3, 4], 'b': (1, 2, 3)}
print(b)  # {'a': [1, 2, 3, 4], 'b': (1, 2, 3, 4, 5), 'c': 100}

3.分片表达式相当于一个浅拷贝

深拷贝

1.对于可变对象的深拷贝,是对一个对象所有层次的递归拷贝

2.对于完全不可变对象类型,不会拷贝仅仅只会指向

3.对于可变对象存在对自身的循环引用,深拷贝也不会StackOverflow,因为深拷贝时会维护一个字典,记录已拷贝对象和id,如果id存在直接返回

import copy

x = [1]
x.append(x)
print(x)
y = copy.deepcopy(x)
print(x == y) #抛错:RecursionError: maximum recursion depth exceeded in comparison

源码

def deepcopy(x, memo=None, _nil=[]):
    """Deep copy operation on arbitrary Python objects.

    See the module's __doc__ string for more info.
    """

    if memo is None:
        memo = {}

    d = id(x)
    y = memo.get(d, _nil)
    if y is not _nil:
        return y
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值