学习整理,若有问题,欢迎指正。

python 可变对象,不可变对象

  1. 可变对象

该对象所指定的内存地址上面的值可以被改变,变量被改变后,其所指向的内存地址上面的值,直接被改变,没有发生复制行为,也没有发生开辟新的内存地址行为。

python可变对象有,列表,字典,set集合

列如:

a = ['1','2','3']

print(id(a))
2275736586376 a.append('1') print(a)
['1', '2', '3', '1'] print(id(a))
2275736586376

我们可以看到,在向 a 列表内追加数据的时候,列表 a 前后的id没有发生变化,所以内存地址内,没有开辟新的空间,而是直接在原指定内存地址上面修改的。

图解:

2. 不可变对象

该对象所指定内存中的值不可以被改变,在改变某个对象的值的时候,由于其内存中的值不可以被改变,所以,会把原来的值复制一份再进行改变,这样就会计算机会开辟

一段新的内存空间来存储新的值,python 不可变对象有 int str float number,tuple,None

例如:

c = 'Hello'

print(id(c))
2237718097848 print(c)
Hello c = c + 'World' print(id(c))
2237720838960 print(c)
HelloWorld

我们可以看到,c变量在追加的时候,两个id是不一样的,所以内存地址会发生变化,此变化为,将c变量所指向的内存,复制一份,然后再做更改。

图解:

此时,c的内存是指向 HelloWorld的,若Hello内存,长时间没有变量指定,则垃圾回收机制会自动回收的。

3. 等于赋值,并不会产生独立的对象单独存在,而是给原来的数据块打上一个新的标签,其中一个标签值被改变的时候,另一个标签也随之改变。

alist = [1,2,3,['a','b','c']]
b = alist
#此处id相同,所以指向同以内存地址
print(id(alist))
2030874445768
print(id(b))
2030874445768
#向alist内追加元素
alist.append(5)
print(alist)
[1, 2, 3, ['a', 'b', 'c'], 5]
print(b)
[1, 2, 3, ['a', 'b', 'c'], 5]
#向alist内的列表追加元素
alist[3].append("d")
print(alist)
[1, 2, 3, ['a', 'b', 'c', 'd'], 5]
print(b)
[1, 2, 3, ['a', 'b', 'c', 'd'], 5]
print(id(alist))
2030874445768
print(id(b))
2030874445768

由上面代码看出,alist所指向 [1,2,3,['a','b','c']] 内存地址,b 也是指定的[1,2,3,['a','b','c']]内存地址(id相同),所以a.append(5)后,alist变化,b也变化

图解:

由上图可以看出,无论alist做什么操作,b的内存地址都是指向alist的,所以alist的任何变化,b都会跟着变化。

4. 浅复制,浅复制分为两种情况

  • 第一种情况,浅复制的值是不可变对象(数值,字符串,元组)时,与等值复制的是一样的,对象的id值与浅复制对象的id是一样的。
import copy

a = 'abcde'
b = a
print(id(a))
2030878234584
print(id(b))
2030878234584 c = copy.copy(a)
print(id(c))
2030878234584 #当改变a的值
a = a + 'fg'
print(id(a))
2030878515304
#由于字符串为不可变对象,所以id(a)会发生变化,但是b,c不会发生变化,还是指向原有内存
print(id(b))
2030878234584
print(id(c))
2030878234584

由上面代码可以看出 b = a 其实b,a是指向同一块内存的(id)相同,c=copy.copy(a)也是和a,b指向同一块内存的(id相同),当a发生变化的时候,a会复制原有值,开辟一块新的内存

出来,此时,c与b还是指向原有内存(观察id)

图解:

  • 当浅复制的值是可变对象(列表和元组)时会产生一个“不是那么独立的对象”存在。有两种情况:

    • 复制的 对象中无 复杂 子对象,原来值的改变并不会影响浅复制的值,同时浅复制的值改变也并不会影响原来的值。原来值的id值与浅复制原来的值不同。

当浅复制的值是可变对象(列表,字典)时,改变的值不是 复杂子对象 代码如下:

list1 = ['1','2','3']
print(id(list1))
2030878577608 list2 = list1
print(id(list2))
2030878577608 list3 = list1.copy()
print(id(list2))
2030878577608
#上面三者id都一致 #然后在list1后面append一个新的元素,查看变化情况
list1.append('4')
print(list1)
['1', '2', '3', '4', '4']
print(id(list1))
2030878577608
print(list2)
['1', '2', '3', '4', '4']
print(id(list2))
2030878577608
print(list3)
['1', '2', '3']
print(id(list3))
2030878531400
#list3的值与list1,list2的值,不一样,且id也不一样了

当list2 = list1 的时候,完全指向同一块内存空间,list3 = list1.copy()的时候,list3也指向同一块内存空间,当list1发生变化的时候,list2与list1开辟出一块新的空间用来改变,list3还指向原有空间(或者相反)

图解:

  • 当浅复制的值是可变对象(列表,字典)时,改变的值是 复杂子对象 代码如下:
l1 = [1,2,['a','b']]
l2 = l1
l3 = copy.copy(l2)
l4 = copy.deepcopy(l3)
print(id(l1))
2030878621960
print(id(l2))
2030878621960
print(id(l3))
2030878622664
print(id(l4))
2030878622728
#id可以看出,l1,l2的id没有改变,但是,l3,l4的id发生了变化
l1[2].append('a')
print(id(l1))
2030878621960
print(l1)
[1, 2, ['a', 'b', 'a']]
print(l3)
[1, 2, ['a', 'b', 'a']]
print(l4)
[1, 2, ['a', 'b']]
#l1[2].append('a')是改变l1内的可变列表的值,l1的id没有变化,值有变化,l3的值有变化,但是l4的值没有变化。
l1.append(3)
print(id(l1))
2030878621960
print(l1)
[1, 2, ['a', 'b', 'a'], 3]
print(l2)
[1, 2, ['a', 'b', 'a'], 3]
print(l3)
[1, 2, ['a', 'b', 'a']]
print(l4)
[1, 2, ['a', 'b']]
#l1.append(3)是改变l1的值,l1id没有变化,l3的值没有被改变(还是和上一步的值一样),l4与l1初始值一样的。

当改变 复杂子对象中的元素时,浅拷贝值发生了变化; 当改变的值不是复杂子对象,浅拷贝的值没有发生变化。因为 浅拷贝 ,复杂子对象的保存方式是 作为 引用 方式存储的,所以修改 浅拷贝的值 和原来的值都可以 改变 复杂子对象的值。

图解:

  • 深度拷贝

    • 即将被复制对象完全再复制一遍作为独立的新个体单独存在。所以改变原有被复制对象不会对已经复制出来的新对象产生影响
    • 上图中已经有说明了。转载

python,可变对象,不可变对象,深拷贝,浅拷贝。的更多相关文章

  1. Python深复制浅复制or深拷贝浅拷贝

    1. copy.copy 浅拷贝 只拷贝父对象,不会拷贝对象的内部的子对象.(比深拷贝更加节省内存)2. copy.deepcopy 深拷贝 拷贝对象及其子对象 用一个简单的例子说明如下: >& ...

  2. python集合增删改查,深拷贝浅拷贝

    集合 集合是无序的,不重复的数据集合,它里面的元素是可哈希的(不可变类型),但是集合本身是不可哈希(所以集合做不了字典的键)的.以下是集合最重要的两点: 去重,把一个列表变成集合,就自动去重了. 关系 ...

  3. Python坑系列:可变对象与不可变对象

    在之前的文章 http://www.cnblogs.com/bitpeng/p/4748148.html 中,大家看到了ret.append(path) 和ret.append(path[:])的巨大 ...

  4. python 可变、不可变类型、深拷贝、浅拷贝理解

    简介 python中数据分为可变类型,不可变类型.不同的数据类型影响着不同情况下的深浅拷贝. 下面则将简要介绍一下 可变类型 当某个数据的值发生改变时,它对应的内存地址不发生改变,常见的有列表.字典. ...

  5. python引用在函数传参时的体现以及可变与不可变对象的对比

    今天偶然看到 vamei 老师的博客 http://www.cnblogs.com/vamei/archive/2012/07/10/2582795.html 讲的是python动态类型以及引用的事儿 ...

  6. 关于python的可变和不可变对象

    在python中所有都是对象,在python中只有list和dict是可变对象,其他都是不可变对象. 具体参照:http://www.cnblogs.com/lovemo1314/archive/20 ...

  7. python中的可变与不可变对象

    Python中的可变对象和不可变对象 什么是可变/不可变对象 不可变对象,该对象所指向的内存中的值不能被改变.当改变某个变量时候,由于其所指的值不能被改变,相当于把原来的值复制一份后再改变,这会开辟一 ...

  8. python函数参数是值传递还是引用传递(以及变量间复制后是否保持一致):取决于对象内容可变不可变

    函数参数传递本质上和变量整体复制一样,只是两个变量分别为形参a和实参b.那么,a=b后,a变了,b值是否跟着变呢?这取决于对象内容可变不可变 首先解释一下,什么是python对象的内容可变不可变? p ...

  9. Python中的可变、不可变对象和赋值技巧序列解包

    可变对象和不可变对象 在python中一切皆对象.在Python中不存在所谓的值传递调用,一切传递都是对象的引用,也可认为是传址. python中,对象分为可变(mutable)和不可变(immuta ...

  10. python 基础使用list、dict、set、可变与不可变对象

    参考链接:https://www.liaoxuefeng.com/wiki/1016959663602400/1017104324028448 dict是字典,可以储存键值对类型的值,set与dict ...

随机推荐

  1. 上传本地文件到GitHub上

    问题解决 今天在windows上上传本地文件到github,出现用户名和仓库不匹配的情况,解决方式如下: 打开控制面板,选择用户账户 把该删除的账户删除一下就行了. 上传文件的步骤如下: 将上传的文件 ...

  2. supervisor管理nginx

    command = /usr/local/bin/nginx 这个命令默认是后台启动,但是supervisor不能监控后台程序,所以supervisor就一直执行这个命令. 加上-g 'daemon ...

  3. 【转】JSON.parse() Unexpected token i in JSON at position 2 报错问题

    JSON.parse(): Unexpected token i in JSON at position 2 报错问题 错误代码: var res = "[{id:1,name:'limin ...

  4. 转://诊断 Grid Infrastructure 启动问题 (文档 ID 1623340.1) .

    文档内容   用途   适用范围   详细信息   启动顺序:   集群状态   问题 1: OHASD 无法启动   问题 2: OHASD Agents  未启动   问题 3: OCSSD.BI ...

  5. BJOI2019做题笔记

    奥术神杖(分数规划.AC自动机) 发现我们要求的东西很像一个平均数(实际上就是几何平均数),那么我们现在考虑一种运算,使得乘法能够变成加法.开根可以变成除法,不难想到取对数满足这个条件.我们对\(\s ...

  6. CF452F Permutations/Luogu2757 等差子序列 树状数组、Hash

    传送门--Luogu 传送门--Codeforces 如果存在长度\(>3\)的等差子序列,那么一定存在长度\(=3\)的等差子序列,所以我们只需要找长度为\(3\)的等差子序列.可以枚举等差子 ...

  7. IPv6绝不仅仅是对IPv4地址长度的增加

    众所周知,IPv6 IP地址长度是IPv4 IP地址长度的四倍,是解决IPv4公共网址资源枯竭的最佳技术.的确,IETF在制定IPv6标准时也是基于这一因素考虑的.当时正是90年代初,Web开始出现, ...

  8. HashMap 与 Hashtable 的区别

    Hashtable t 小写 二者用法一致   都实现Map接口 1.HashMap 的键值可以为null,而Hashtable不允许("null" 不是 null 前者是字符串 ...

  9. Teching Yourself Programming in Ten Years -Peter Norvig

    http://norvig.com/21-days.html 我们经常能看到“7天搞定51单片机”.“21天学会C++”这样样式的标题,编程真的很容易吗?似乎比其他事情要简单很多呀!是的,糟糕的编程确 ...

  10. python爬取中国天气网站数据并对其进行数据可视化

    网址:http://www.weather.com.cn/textFC/hb.shtml 解析:BeautifulSoup4 爬取所有城市的最低天气   对爬取的数据进行可视化处理 按温度对城市进行排 ...