可变类型与不可变类型、引用、深拷贝与浅拷贝

基本类型

参考博文:https://www.cnblogs.com/miaomiaokaixin/p/11497813.html

以下进行简单概括,具体细节请阅读上述博文


六种数据类型分类

​ 不可变数据(3个):Number、String、Tuple

​ 可变数据(3个):List、Dictionary、Set


python赋值(=):数据完全共享(博文中有例子说明,很清晰)

赋值是在内存中指向同一个对象:

如果是可变(mutable)类型,比如列表、字典、集合,修改其中一个,另一个必定改变

如果是不可变类型(immutable),比如数字、字符串、元组,修改了其中一个,另一个并不会变


python浅拷贝(博文中有例子和图解)

1.浅拷贝:数据半共享(拷贝第一层的数据,具有自己单独的内存地址;嵌套层即第二层或其他层不拷贝,指向原有的内存地址)

2.原则

只复制一层,他变我不变;其余层,他变我也变。
如果只有一层,就相当于深拷贝了

3.方法-三种

第一种:a = b[:]
第二种:a = b.copy()
第三种:引用copy模块,import copy | a = copy.copy(b)


python深拷贝(博文中有例子和图解)

1.深拷贝:数据完全不共享(复制其数据完完全全放独立的一个内存,完全拷贝,数据不共享)

2.原则

他变我也变。

3.方法

引用copy模块,import copy | a = copy.deepcopy(b)



补充:

除了基本类型, 我总结下我常用的数据类型:

可变数据:array, tensor

1.numpy.array

>>> import numpy as np
>>> 
>>> a = np.array([[1, 3, 2], [3,2, 1], [7, 8, 9]])
>>> a
array([[1, 3, 2],
       [3, 2, 1],
       [7, 8, 9]])
b = a
>>> b
array([[1, 3, 2],
       [3, 2, 1],
       [7, 8, 9]])
>>> a[1, 0] = 10    #相同地址的一个变量修改, b也发生变化
>>> a
array([[ 1,  3,  2],
       [10,  2,  1],
       [ 7,  8,  9]])
>>> b
array([[ 1,  3,  2],
       [10,  2,  1],
       [ 7,  8,  9]])
>>> c = b.copy()   #此时已经是深拷贝了, b变c不变,使用deepcopy也可完成深拷贝
>>> b
array([[ 1,  3,  2],
       [10,  2,  1],
       [ 7,  8,  9]])
>>> c
array([[ 1,  3,  2],
       [10,  2,  1],
       [ 7,  8,  9]])
>>> b[1, 0] = 100
>>> b
array([[  1,   3,   2],
       [100,   2,   1],
       [  7,   8,   9]])
>>> c
array([[ 1,  3,  2],
       [10,  2,  1],
       [ 7,  8,  9]])

2.tensor

tensor与numpy一样,是可变数据类型, 但实现深拷贝的方式是使用copy模块中的deepcopy()

id()、is、==

id()

​ 查看当前变量的地址值,注意如果同样赋值为1, 可能对应的地址是不相等的, 因为可能分配了不同的地址

另, id不同也可能是浅拷贝,如list使用.copy()、copy()时id不同,但是是浅拷贝,代码如下

>>> a = [[1, 2, 3, 4], [3, 4, 1, 5]]
>>> b = a
>>> c = a.copy()
>>> d = copy(a)
>>> e = deepcopy(a)
>>> id(a) == id(b)    #判断地址是否相同
True
>>> id(a) == id(c)
False
>>> id(a) == id(d)
False
>>> id(a) == id(e)
False
>>> a[0][0] = 100     #修改值
>>> a
[[100, 2, 3, 4], [3, 4, 1, 5]]
>>> b
[[100, 2, 3, 4], [3, 4, 1, 5]]  #c、d 与a地址不同,但是a变c、d也变化
>>> c
[[100, 2, 3, 4], [3, 4, 1, 5]]
>>> d
[[100, 2, 3, 4], [3, 4, 1, 5]]
>>> e                         #e是深拷贝,没有变化
[[1, 2, 3, 4], [3, 4, 1, 5]]

is

​ 判断id是否相等

==

​ 判断值是否相等

>>> a = np.array([[1, 3, 2], [3,2, 1], [7, 8, 9]])
>>> a = torch.tensor(a)
>>> b = a
>>> id(a)
140045026533664
>>> id(b)
140045026533664
>>> c = deepcopy(a)   #深拷贝
>>> id(c)
140045026533592
>>> d = a
>>> id(d)
140045026533664
>>> id(d)
140045026533664
>>> id(a)
140045026533664
>>> a is d
True
>>> a is c	   #c是深拷贝, id 不相等
False
>>> c is b     #c是深拷贝, id 不相等
False
>>> b is a
True
>>> b is d
True
>>> c == b      #id不同,但值相同
tensor([[True, True, True],
        [True, True, True],
        [True, True, True]])


过程讲解

参考博文:https://blog.csdn.net/hohaizx/article/details/78427406


赋值

首先需要明确的是,Python中一切事物皆对象,变量是对对象在内存中的存储和地址的抽象。
img

“=”(赋值号)是将右侧对象的内存地址赋值给左侧的变量。
当我们写下面语句时:

a = “abc”

1

Python解释器其实顺序干了两件事情:
1、在内存中创建一个字符串“abc”;
2、在内存中创建一个名为“a”的变量,并将“a”指向字符串“abc”(将“abc”的地址保存到“a”中)。
这样我们就能通过操作“a”而改变内存中的“abc”。
所以执行下面语句

a = “123”
b = a
a = “xyz”

1
2
3

执行第一句Python解释器创建字符串“123”和变量“a”,并把“a”指向“123”。
在这里插入图片描述

执行第二句,因为“a”已经存在,并不会创建新的对象,但会创建变量“b”,并把“b”指向“a”指向的字符串“123“。
在这里插入图片描述

执行第三句,首先会创建字符串“xyz”,然后把“xyz”的地址赋予“a“(“a”指向字符串“xyz”)。
在这里插入图片描述

我们可以通过调用id()方法查看变量所指向对象在内存中的地址。

a = “123”
id(a) # 2248238011648,这个数字就代表了a所指向的对象在内存中地址

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值