Python可变对象和不可变对象

要点:Python为动态型语言,对象和引用分离,属于传址调用;

         Python的数据分为可变对象和不可变对象;

         以上两者共同决定变量引用中的赋值变化


1. 动态语言的对象和引用分离

Python属于动态语言,引用和对象分离(动态类型的核心),在内存中,引用和对象将分别创建,同时将变量指向实体对象

a = 198  # 在内存中分别创建198的int对象和名称为a的变量;并将变量a指向198 
b = a  # 在内存中创建名为b的变量,并将b指向a所引用的对象198
d = [1,2,3] # 过程同上
e = d


2. 可变和不可变对象说明

可变对象:通过引用变量可以改变自身的对象类型。

      a.  可以有多个相同对象;

      b. 赋值语句会创造新的对象;

      c.  列表(list)和字典(dictionary)属于可变对象

不可变对象:不能改变对象本身,只能改变引用指向的对象类型。

      a. 每个不可变对象在内存中只存有一份(Python会缓存);

      b. 赋值语句对于已经存在的不可变对象,只是增加新的指向

      c. 数字(int、float)、字符串(string)和元组(tuple)属于不可变对象

自我理解:

    变量:“咱改变一下,来点刺激的吧!!!“

    可变对象:“哥,听你的,你想咋变,我就咋变“

    不可变对象:“切,姐还嫌弃你了呢,想变找别人去,姐不伺候了,我走“

a = a + 1  # 不可变对象-->>创建199的对象,a重新指向199,b还是指向198
d[0] = d[0] + 1  # 可变对象-->>[1,2,3]将变为[2,2,3],所以e也会跟随变化

3. 函数演示内部变化

主要用到id()获取对象的内存地址

a = 111111111   
b = a  
c = 111111111   
  
d = [1,3,5]  
e = d  
f = [1,3,5]  
print("*********************")  
print("1. 赋值的不同")  
print("   1.1 不可变对象")  
print("       a = %s;id(a) = %s"%(a,id(a)))  
print("       b = %s;id(b) = %s"%(b,id(b)))  
print("       c = %s;id(c) = %s"%(c,id(c)))  
print("   1.2 可变对象")  
print("       d = %s;id(d) = %s"%(d,id(d)))  
print("       e = %s;id(e) = %s"%(e,id(e)))  
print("       f = %s;id(f) = %s"%(f,id(f)))  
  
a = a + 1  
d[0] =  d[0] + 1  
  
print("2. 运算的不同")  
print("   2.1 不可变对象")  
print("       a = %s;id(a) = %s"%(a,id(a)))  
print("       b = %s;id(b) = %s"%(b,id(b)))  
print("       c = %s;id(c) = %s"%(c,id(c)))  
print("   2.2 可变对象")  
print("       d = %s;id(d) = %s"%(d,id(d)))  
print("       e = %s;id(e) = %s"%(e,id(e)))  
print("       f = %s;id(f) = %s"%(f,id(f)))  
  
# 结果如下:  
# *********************  
# 1. 赋值的不同  
#    1.1 不可变对象  
#        a = 111111111;id(a) = 6153072    
#        b = 111111111;id(b) = 6153072  
#        c = 111111111;id(c) = 6153072  # 新的赋值语句仍然指向原来的内存地址
#    1.2 可变对象  
#        d = [1, 3, 5];id(d) = 6876176  
#        e = [1, 3, 5];id(e) = 6876176  
#        f = [1, 3, 5];id(f) = 6876016  # 新的赋值语句创建了新的对象
# 2. 运算的不同  
#    2.1 不可变对象  
#        a = 111111112;id(a) = 5592536  # 运算后,由111111111-->111111112,所以a的引用发生变化
#        b = 111111111;id(b) = 6153072  # 变化后,b的取值没有变化,仍然引用111111111
#        c = 111111111;id(c) = 6153072  
#    2.2 可变对象  
#        d = [2, 3, 5];id(d) = 6876176  # 由[1,3,5]-->[2,3,5],但是内存地址没有发生变化
#        e = [2, 3, 5];id(e) = 6876176  # 由于引用的内存地址上的数据变化,导致e也变为[2,3,5]
#        f = [1, 3, 5];id(f) = 6876016  

4. 参数调用的变化

def bukebian(x):  
    x = 100  
    print("   函数值:x = %s;id(x) = %s"%(x,id(x)))  
def kebian(y):  
    y[0]=100  
    print("   函数值:y = %s;id(y) = %s"%(y,id(y)))  
m = 1  
n = [1,2,3,4]  
print("1. 不可变对象")  
print("   变化前:m = %s  ;id(m) = %s"%(m,id(m)))  
bukebian(m)  # 不可变对象函数中引用  
print("   变化后:m = %s  ;id(m) = %s"%(m,id(m)))  
print("2. 可变对象")  
print("   变化前:n = %s  ;id(n) = %s"%(n,id(n)))  
kebian(n)  # 可变对象函数中引用  
print("   变化后:n = %s;id(n) = %s"%(n,id(n)))  
# 变化结果如下:  
#1. 不可变对象  
#   变化前:m = 1  ;id(m) = 1420576400  
#   函数值:x = 100;id(x) = 1420577984  # 参数调用m,其实是x引用1;x重新赋值为100,其实是x重新引用100
#   变化后:m = 1  ;id(m) = 1420576400  # m因为仍然指向1,所以没有发生变化
#2. 可变对象  
#   变化前:n = [1, 2, 3, 4]  ;id(n) = 6417424  
#   函数值:y = [100, 2, 3, 4];id(y) = 6417424  # 调用[1,2,3,4]后,内存地址不变,但可变对象的值发生变化
#   变化后:n = [100, 2, 3, 4];id(n) = 6417424  # 引用的内存地址虽然没变,但内存地址存储的数据发生变化

总结:

变量引用不可变对象,只要是不重新赋值,引用的数据不会发生变化;

变量引用可变对象,其数据随着引用对象的变化而变化

参考资料

Python学习笔记——可变对象和不可变对象

Python深入06 Python的内存管理

Python进阶09 动态类型


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值