关于python变量的引用以及在底层存储原理

目录
  • 1.变量的引用的底层原理
  • 2.变量的分类

Python的变量,简单来说有数值型,布尔型,字符串类型,列表,元组,字典等6大类。那么不同变量类型在底层是如何存储的,关系到变量的引用,能否正确的掌握变量的相关操作

下面v1,v2的值分别是多少?为什么?

v1 =3
v2=v1
print("v2:",v2)
v1 += 2
print("v1:",v1)
print("v2:",v2)

#下面l2的值又是多少?为什么?

l1 = [1,2,3]
l2 =l1
print(l2)
l1.append(4)
print(l2)

1.变量的引用的底层原理

v1 =3
v2=v1
print("v2:",v2)
v1 += 2
print("v1:",v1)
print("v2:",v2)   #v1的值变化了,为什么v2的值没有跟着变化呢?
'''

执行结果如下:

v1: 5
v2: 3
'''

l1 = [1,2,3]
l2 =l1
print(l2)
l1.append(4)
print(l2)    #l1的值变化了,但是为什么l2的值也跟着变化了。
'''

执行结果如下:

[1, 2, 3]
[1, 2, 3, 4]

'''

要点分析:

  • 可变对象和不可变对象:不可变对象包括intfloatstringtuple等。可变对象包括list,dict,自定义类的实例等。
  • python中通过= 复制的变量,都是同时即把变量的值,也把变量在内存中的地址复制也过去了。即=复制过的变量不仅内存地址一样,变量的值也一样。但是需要注意的是:对于不可变类型(如int)的变量,如果要更改变量的值,则会创建一个新值,并且给这个新值分配一个新的内存地址,然后把变量指向这个新值的内存地址上,而旧值如果没有被引用就等待垃圾回收。如果是可变类型变量。如果修改变量的值,则可以直接修改变量的值,变量的引用地址不会变。

不可变类型:变量赋值 a=5 后再赋值 a=10,这里实际是新生成一个 int 值对象 10,再让 a 指向它,而 5 被丢弃,不是改变a的值,相当于新生成了a。

可变类型:变量赋值 la=[1,2,3,4] 后再赋值 la[2]=5 则是将 list la 的第三个元素值更改,本身la没有动,只是其内部的一部分值被修改了。

  • 本质是因为不可变对象一旦新建后,系统就会根据他的大小给他分配固定死的内存,所以不允许修改,只修改值只能申请新的内存和地址。而可变对象,他的内存大小可以随着值的变化而自动扩容

代码分析演示:

因为变量在内存中新建时,系统都会给他分配一个地址,然后通过地址去查找或引用他的值。  Python的所有变量其实都是指向内存中的对象的一个指针,都是值的引用

代码演示1:

v1 =3
v2=v1
print("v1在内存的地址:%d,v2在内存中地址:%d"%(id(v1),id(v2)))
v1 += 2
print("v1在内存的地址:%d,v2在内存中地址:%d"%(id(v1),id(v2)))
print("v1:",v1)
print("v2:",v2)
========================================================
v1在内存的地址:1747378992,v2在内存中地址:1747378992
v1在内存的地址:1747379024,v2在内存中地址:1747378992
v1: 5
v2: 3
'''

因为:v1,v2都是int,为不可变对象,所以一旦修改他们的值,包扣加减乘除赋值等操作,系统会在内存中给他们重新创建一个。
然后再把这个变量绑定(通过地址引用)到这个值上,所以v1 +=2后,他在内存中的地址变了。而v2依旧引用的是之前的地址,所以v2的值
没有更新。
'''

代码演示2:

l1 = [1,2,3]
l2 =l1
print("l1在内存的地址:%d,l2在内存中地址:%d"%(id(l1),id(l2)))
print(l2)
print("l1在内存的地址:%d,l2在内存中地址:%d"%(id(l1),id(l2)))
l1.append(4)
print(l2)
print("l1在内存的地址:%d"%(id(l1)))
=======================================================
l1在内存的地址:37345880,l2在内存中地址:37345880
[1, 2, 3]
l1在内存的地址:37345880,l2在内存中地址:37345880
[1, 2, 3, 4]
l1在内存的地址:37345880

对于可变对象如列表,l1,l2,当修改他们的值时,系统会自动在原地址上给他们扩容内存,所以不用修改地址。

代码演示3:同理字符串等不可变的变量引用效果也一样。

str1 ='hahhahah'
str2 = str1
str1 += "123"
print(str1,str2)
hahhahah123 hahhahah

2.变量的分类

可变类型与不可变类型

可变类型,值可以改变:

  • 列表 list
  • 字典 dict

不可变类型,值不可以改变:

  • 数值类型 int, long, bool, float
  • 字符串 str
  • 元组 tuple

到此这篇关于关于python变量的引用以及在底层存储原理的文章就介绍到这了,更多相关python变量的引用以及在底层存储原理内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • python游戏的魅力之冒险岛实战项目

    目录 导语 正文 效果图: 总结 导语 ​哈喽哈喽!我是木木子. 新的一天又开始了~ ​ 是的,今天是大工程,​又到了每日更新游戏环节,你们有期待吗? ​ 想了很久,这游戏估计你们也没玩过,比较少见吧!最近家里的孩子一直在沉迷<梦幻国度>. 让他见识下python的魅力,能学习也能做游戏的.不能一直玩撒~学习也很重要嘛 今天想说我们直接开始制作一款Python玛丽冒险岛游戏~ 正文 ​ ​(1)环境安装部分: Python版本:Python 3.6 开发工具:PyCharm.Python内置模

  • Python中is与==的使用区别详解

    目录 一.== 是比较两个对象的内容是否相等 二.is 比较的是两个实例对象是不是完全相同 三.使用is注意python对于小整数使用对象池存储问题 四.使用is注意python关于字符串的intern机制存储 5.python中对于None值的比较:使用is 一.== 是比较两个对象的内容是否相等 即两个对象的"值""是否相等,不管两者在内存中的引用地址是否一样. //地址一样,值也一样.所以==成立. st1 ='aaaaa' st2 = 'bbbbb' st3 = 'b

  • Python 多继承中的一个诡异现象 既是 Father又是grandfather

    目录 我们知道,在面向对象编程里面, 继承 是一个很重要的概念.子类可以使用父类的方法和属性. 例如下面这段代码: class Father: def __init__(self): self.address = '上海' def say(self): print('我是爸爸') class Son(Father): def __init__(self): super().__init__() def say(self): print('我是儿子') son = Son() print(son.

  • python 基于 tkinter 做个学生版的计算器

    目录 导语 正文 总结 导语 九月初家里的熊孩子终于开始上学了! 半个月过去了,小孩子每周都会带着一堆的数学作业回来,哈哈哈哈~真好,在家做作业就没时间打扰我写代码了. 很赞,鹅鹅鹅饿鹅鹅鹅~曲项向天歌~~~~开心到原地起飞. 孩子昨天回家之后吃完饭就悄咪咪的说,神神秘秘的我以为做什么?结果是班主任让他们每个人带一个计算器,平常做数学算数的时候可以在家用用,嗯哼~这还用卖嘛? 立马给孩子用Python制作了一款简直一摸一样的学生计算器~ ​​ 正文 本文的学生计算器是基于tkinter做的界面化

  • python游戏实战项目之俄罗斯方块的魅力

    目录 导语 正文 效果图: ​总结 导语 ​ 为什么有这么一个简单的游戏?这个游戏如此受欢迎? 仅仅是因为它在游戏行业异常匮乏的年代出现,从而成为了一代人的记忆吗?恐怕并不是. 玩过俄罗斯方块的人都明白,它给人的感觉就像是嗑瓜子一样,一旦开始就会像上瘾一样难以停下来,绞尽脑汁只想填满空缺的地方. ​ 哈哈哈!小编每周的话基本上都会整理一些游戏代码的哈! 这一期文章就带大家来开发一款俄罗斯方块小游戏! 正文 游戏规则:由小方块组成的不同形状的板块陆续从屏幕上方落下来,玩家通过调整板块的位置和方向,

  • python全局变量引用与修改过程解析

    这篇文章主要介绍了python全局变量引用与修改过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 一.引用 使用到的全局变量只是作为引用,不在函数中修改它的值的话,不需要加global关键字.如: #! /usr/bin/python a = 1 b = [2, 3] def func(): if a == 1: print("a: %d" %a) for i in range(4): if i in b: print(&quo

  • 童年回忆录之python版4399吃豆豆小游戏

    目录 前文 正文 结尾 前文 昨天家里来人,老姐的小孩儿抢着跟我玩电脑,result........很久很久之后!! 那你想错了,我可不是欺负小孩子的那种人.老实人本人.三秒之后就给她了. 看见她在4399玩了一款小游戏,感觉很适合小孩子.emmmmmm...... ​ 灵感来了挡都挡不住,嗯哼~今天正入正题,开发一款4399类似的吃豆豆小游戏,等着!!!! 正文 Python版本:3.6.4 相关模块: pygame模块: 以及一些Python自带的模块. 模块自行安装.环境安装包等新手小白不

  • Python中优雅使用assert断言的方法实例

    目录 什么是 assert 断言 断言和异常的使用场景 使用断言的几个原则 建议不使用断言的情况: 总结 什么是 assert 断言 Assert statements are a convenient way to insert debugging assertions into a program 断言声明是用于程序调试的一个便捷方式.断言可以看做是一个 debug 工具,Python 的实现也符合这个设计哲学,在 Python 中 assert 语句的执行是依赖于__debug__这个内置

  • python共享引用(多个变量引用)示例代码

    复制代码 代码如下: a = 3b = a 先上图(图1)吧,大家一看就一目了然了: 变量名和对象,在运行赋值语句b = a之后,变量a,b都指向了对象3的内存空间.假设这时执行 a = 'python', a将指向刚创建的字符串对象.我们再来试试这种情况: 复制代码 代码如下: >>>list_1 = [1,2,3,4]>>>list_2 = list_1>>>list_2>>>list_1[0] = 'python'>>

  • 聊聊Python中的@符号是什么意思

    Python中的@符号是装饰器的意思.Python中装饰器本质上就是一个函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外的功能,装饰器的返回值也是一个函数对象(函数的指针). 实质:是一个函数 参数:是你要装饰的函数名(并非函数调用) 返回:是装饰完的函数名(也不是函数调用) 作用:为已经存在的对象添加额外的功能. 特点:不需要对对象做任何的代码上的变动. Python装饰器有很多经典的应用场景,比如:插入日志,性能测试,事务处理,权限校验等.装饰器是解决这类问题的绝佳设计. 装饰器

  • python游戏实战项目之童年经典超级玛丽

    导语 "超级玛丽"--有多少人还记得这款经典游戏?那个戴帽子的大胡子穿着背带裤的马里奥! 带您重温经典的回忆,超级马里奥拯救不开心!炫酷来袭. 如果您的童年,也曾被魔性的 灯~灯灯~灯~灯灯~灯洗脑~那就来怀旧一番吧! 我是华丽的分割线------------------------------ 往期写过游戏实战已经积累到30几篇了哦~嘿嘿,推一波之前的,狗头保命.jpg. 欢迎大家来领免费的游戏,开玩啦~源码可以直接找我拿滴! 在座的各位大佬,你们都玩过这里面的几个游戏吖? ​ 往期

  • python 如何将字典写为json文件

    目录 python 将字典写为json文件 字典结构如下 写为json Python txt文件读取写入字典(json.eval) 使用json转换方法 使用str转换方法 python 将字典写为json文件 字典结构如下 res = { "data":[] } temp = { "name":name, "cls":cls } res["data"].append(temp) 写为json 具体代码如下: json_dat

随机推荐