一. 问题的提出

我们先来看两个对比

第一道题,当对象为整数时,最终结果:b = 2, a = 1,b的变化没有引起a的变化

a = 1
b = a
b += 1

print(a)
print(b)

结果:
1
2

第二道题,当对象为字典时,最终结果:a = {"name":"jack","age":27}, b = {"name":"jack","age":27},b的变化引起了a的变化

a = {"name": "Jack"}
b = a
b["age"] = 27

print(a)
print(b)

结果:
{"name":"Jack","age":27}
{"name":"Jack","age":27}

那么,为什么上述两道题的结果会有如此大的区别呢?我们就来了解一下可变数据类型和不变数据类型

二. 可变数据类型和不可变数据类型

  • 可变数据类型有:列表list、字典dict
  • 不可变数据类型有:整型int、浮点型float、字符串string和元组tuple

python中有一个id()函数,可用来获取对象的内存地址,我们针对第一题,可以看一下a和b指向的对象的内存地址有什么变化

>>> a = 1
>>> b = a
>>> id(a)
1814284368
>>> id(b)
1814284368
>>> b += 1
>>> id(b)
1814284400
>>> id(a)
1814284368
>>> 

我们可以清晰的看到,a = 1, b = a,这两个操作中,变量a和b指向的对象的内存地址是一样的,也就是说a和b其实引用了同一个对象1。那为什么整型是不可变数据类型呢?这里可以理解为a和b的引用地址处的值是不能被改变的,也就是1814284368地址处的值在没被垃圾回收之前一直是1,不能改变,如果把b赋值为2,那么,只能把b的引用地址从1814284368变为1814284400,相当于b += 1这个赋值又创建了一个新的对象2,然后变量a仍然指向对象1,而变量b指向了对象2,变量b的变化并不会引起a的改变,因为它们指向的是不同的对象

我们大概画个演示图:

图一:a = 1, b = a

图二: b += 1

我们再来看字典,先用id()看一下内存地址的变化

>>> a = {"name": "Jack"}
>>> b = a
>>> id(a)
59071624
>>> id(b)
59071624
>>> b["age"] = 27
>>> id(a)
59071624
>>> id(b)
59071624
>>> a
{'age': 27, 'name': 'Jack'}
>>> b
{'age': 27, 'name': 'Jack'}

可以看到,变量a和b同时指向一个字典对象,当给变量b指向的字典添加元素后,b指向的字典的内存地址并不会发生变化,也就是说,对b的操作不会改变a引用的地址值,相当于同样一个地址得到了扩充,由于a和b指向同一个地址,所以b的变化会引起a的变化

图一:a = {"name": "Jack"}, b = a

图二:b["age"] = 27

三. 参考文章

https://blog.csdn.net/dan15188387481/article/details/49864613

一道问题引出的python中可变数据类型与不可变数据类型的更多相关文章

  1. 简单谈谈Python中的几种常见的数据类型

    简单谈谈Python中的几种常见的数据类型 计算机顾名思义就是可以做数学计算的机器,因此,计算机程序理所当然地可以处理各种数值.但是,计算机能处理的远不止数值,还可以处理文本.图形.音频.视频.网页等 ...

  2. Python中函数的参数传递与可变长参数

    转自旭东的博客原文 Python中函数的参数传递与可变长参数 Python中传递参数有以下几种类型: (1)像C++一样的默认缺省函数 (2)根据参数名传参数 (3)可变长度参数 示例如下: (1)默 ...

  3. Python中比较特殊的几种数据类型list、tuple、dict、set

    list list(列表)是Python内置的一种数据类型,它是一种有序.可变的集合,可以随时添加和删除其中的元素. >>> classmates = ['Li', 'Tom', ' ...

  4. python中的引用传递,可变对象,不可变对象,list注意点

    python中的引用传递 首先必须理解的是,python中一切的传递都是引用(地址),无论是赋值还是函数调用,不存在值传递. 可变对象和不可变对象 python变量保存的是对象的引用,这个引用指向堆内 ...

  5. python中 使用join()方法 对各种数据类型中元的素进行合并拼接

    "连接符".join(列表或元组或字符串或字典) 返回的是一个使用连接符进行拼接的字符串 如果对象是列表,元组,就是以一个下标元素为单位进行拼接 如果对象是字符串,就是一个单词元素 ...

  6. Python中的几种数据类型

    大体上把Python中的数据类型分为如下几类:   Number(数字) 包括int,long,float,complex String(字符串) 例如:hello,"hello" ...

  7. (四)Python中的“四大才子”(字符串、列表、字典、集合)

    前戏:在python中把数据序列分为可变(mutable)和不可变(immutable)两种 不可变:string.int.float.tuple 特点:相同对象只是占用一个内存地址,不管有多少个变量 ...

  8. python中的集合

    在python中,普通集合是可变数据类型 通过以下案例说明: >>> s = {1, 2, 3, 4} >>> id(s) 2108634636808 >&g ...

  9. python中的元组

    在python中,元组是不可变类型 可通过以下案例说明: >>> c1 = ['1','2'] >>> c = (1,2,c1) >>> c (1 ...

随机推荐

  1. 一、2440裸机点亮led

    从代码開始(先写一个像普通单片机一样的代码): /********led.c************************/ #define GPFCON  (*(volatile unsigned ...

  2. 【生产问题】--8KW的数据表导致业务卡顿

    问题描述:业务突然变得巨卡 分析思路: (1)分析用户请求进程:查看是否有长期运行霸占锁的情况,或者进程数量巨多.很明显我这里就是巨多,正常情况一般0~40来个的样子,在业务使用高峰期居然达到了140 ...

  3. 卸载SQL Server 2008 (R2)

    一.卸载SQL Server 2008 (R2) 1.找到控制面板,win8及win7都可以直接点解“开始”按钮找到. (Tip:win10系统的小盆友可以在“开始”菜单下点击“所有应用”,找到win ...

  4. 剑指offer 面试56题

    面试56题: 题目:数组中数字出现的次数 题:一个整型数组里除了两个数字之外,其他的数字都出现了两次.请写程序找出这两个只出现一次的数字. 解题思路: 方法一:异或运算,详见<剑指offer&g ...

  5. 蓝图、基于DBUtils实现数据库连接池、上下文管理等

    基于DBUtils实现数据库连接池 小知识: 1.子类继承父类的三种方式 class Dog(Animal): #子类 派生类 def __init__(self,name,breed, life_v ...

  6. Loadrunder脚本篇——Run-time Settings之Preferences

    打开Preferences设置对话框,这里提供了对运行时的参数选择设置 Enable Image and Text Check 开启图片和文本检查.允许用户在回放期间通过web_find(文本检测)或 ...

  7. asp.net Cookie 用户登陆时记住我

    /// <summary> /// 判断Cookie中存储的数据 /// </summary> protected void CheckUserCookie() { //先判断 ...

  8. Oracle表约束

    约束的概述: 约束是在表中定义的用于维护数据库完整性的一些规则 (1).主键约束 不能为空也不能重复 在一个表中只能定义一个主键约束 Oracle会在主键上建立一个唯一索引,可以指定唯一索引的存储位置 ...

  9. flask实现模仿知乎

    上个月花了一个月的时间学习flask框架实现了一个简陋的知乎,有提问,回答,写文章,个人信息页,个人信息修改等功能,因刚接触学习flask,后端代码实现很多冗余,依旧需要修改. github: htt ...

  10. 在看 jquery 源码中发现的一些优化方向

    1. 避免使用 $.fn.each 或 $.each 因为它比原生的 for/while 真的会慢一些,循环次数越多差距越大. 另外,对象的 for-in 比 for 是要快一丢丢的,但数组的 for ...