Python 可变类型和不可变类型,以及其引用
基本数据类型的引用
在Python中定义一个数据便在内存中开辟一片空间来存储这个变量的值,这块已经被分配的内存空间便会有一个内存地址。访问这块内存需要用到变量名,变量名实际存储的是变量的地址在内存中的地址,但是使用print()函数得到的确实这块内存中实际的地址。这个就当成规定就好,没必要纠结。
获得变量在内存中的地址,可以使用id()函数。
常规使用
变量之间的赋值其实是把一个变量的内存地址传递给另一个变量,这样两个变量便都指向内存中的同一块空间,因此这两个变量的之是相等的
a = 1 b = a print("a:%d b:%d" % (a,b)) print(id(a)) print(id(b)) 结果: a:1 b:1 1711072016 1711072016
此时如果有第三个变量c的值与a的相等,那么c的地址与a的地址一样。这一点请大家牢记。
a = 1 c = 1 print("a:%d c:%d" % (a,c)) print(id(a)) print(id(c)) 结果: a:1 c:1 1711072016 1711072016
此时如果修改变量c的值,那么会在内存中新开辟一块内存来存储这个变量,这块新的内存地址将会赋值给c。
a = 1 c = 1 c = 2 print("a:%d c:%d" % (a,c)) print(id(a)) print(id(c)) 结果: a:1 c:2 1711072016 1711072032
基本数据类型作为函数参数
基本数据类型作为函数实参同样是这个道理。
a = 1 print(id(a)) def func(x): print(id(x)) x = 2 print(id(x)) func(a) 结果: 1711072016 1711072016 1711072032
列表、字典等高级数据类型的引用
列表字典等高级数据类型的变量名同样存储的变量的实际地址,一个列表名赋值给另一个变量,那么这两个变量便指向内存中的同一块地址。
list1 = [1,2,3] list2 = list1 print(list1,list2) print(id(list1),id(list2)) 结果: [1, 2, 3] [1, 2, 3] 57931896 57931896
高级数据类型在每集加载进内存的时候内存地址与上一次可能会不同。
此时如果修改list2,也会影响list1的值,但是两个变量在内存中的地址还是不变的。这一点是与基本数据类型不一样的。
list1 = [1,2,3] list2 = list1 print(list1,list2) print(id(list1),id(list2)) list2.append(4) print(list1,list2) print(id(list1),id(list2)) 结果: [1, 2, 3] [1, 2, 3] 43841656 43841656 [1, 2, 3, 4] [1, 2, 3, 4] 43841656 43841656
此时如果有第三个列表list3的值也是[1,2,3,4],可以推测list3的地址与list1的地址应该是一样的,但是事实并非如此。如果有第三个列表list3的值也是[1,2,3,4],相当于在内存中新开辟一块内存来存储这个值。
list1 = [1,2,3] list2 = list1 list3 = [1,2,3] print(list1,list2,list3) print(id(list1),id(list2),id(list3)) 结果: [1, 2, 3] [1, 2, 3] [1, 2, 3] 16775288 16775288 16776768
可变数据类型与不可变数据类型
在python中哪些是可变数据类型,哪些是不可变数据类型。可变数据类型:列表list和字典dict;不可变数据类型:整型int、浮点型float、字符串型string和元组tuple。
用一句话来概括上述过程就是:“python中的不可变数据类型,不允许变量的值发生变化,如果改变了变量的值,相当于是新建了一个对象,而对于相同的值的对象,在内存中则只有一个对象,内部会有一个引用计数来记录有多少个变量引用这个对象;可变数据类型,允许变量的值发生变化,即如果对变量进行append、+=等这种操作后,只是改变了变量的值,而不会新建一个对象,变量引用的对象的地址也不会变化,不过对于相同的值的不同对象,在内存中则会存在不同的对象,即每个对象都有自己的地址,相当于内存中对于同值的对象保存了多份,这里不存在引用计数,是实实在在的对象。
原文地址:https://www.cnblogs.com/xxxtony/p/11595132.html
- mvc路由配置.html结尾的伪静态
- 【编程基础】Java的接口和抽象类
- 循序渐进调优union相关的sql(r2笔记23天)
- 对分区表导入导出的水平,垂直切分(r2第22天)
- 巧用parallel极速提升数据加载速度(r2第21天)
- 【Windows编程】创建多文档界面
- 生产环境sqlldr加载性能问题及分析之二(r2第20天)
- [Python]从豆瓣批量获取看过电影的用户列表,并应用kNN算法预测用户性别
- 关于desc的一个奇怪问题及分析(r2第18天)
- R语言进行中文分词,并对6W条微博聚类
- 只言片语分析datapump的工作原理(r2第18天)
- 开发 | TensorFlow全新的数据读取方式:Dataset API入门教程
- 用python实现支持向量机对婚介数据的用户配对预测
- SQL*Loader-805的解决(r2笔记36天)
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法