当前位置 博文首页 > 文章内容

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

    作者:shunshunshun18 栏目:未分类 时间:2021-09-18 14:44:48

    本站于2023年9月4日。收到“大连君*****咨询有限公司”通知
    说我们IIS7站长博客,有一篇博文用了他们的图片。
    要求我们给他们一张图片6000元。要不然法院告我们

    为避免不必要的麻烦,IIS7站长博客,全站内容图片下架、并积极应诉
    博文内容全部不再显示,请需要相关资讯的站长朋友到必应搜索。谢谢!

    另祝:版权碰瓷诈骗团伙,早日弃暗投明。

    相关新闻:借版权之名、行诈骗之实,周某因犯诈骗罪被判处有期徒刑十一年六个月

    叹!百花齐放的时代,渐行渐远!



    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