一. 问题的提出

我们先来看两个对比

第一道题,当对象为整数时,最终结果: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. js实现文字列表无缝向上滚动

    body{font-size:12px} #demo{overflow:hidden; height:80px; width:280px; margin:90px auto; position:rel ...

  2. 基础篇-java开发

    开局必知 1.变量 在java中,以{}为作用域,所以就存在成员变量和局部变量之说 由于java是强类型语言,所以在申明变量的时候,必须指定类型 java里,一个变量有声明过程和初始化过程(也就是赋值 ...

  3. Vue中浏览器的的前进和后退

    项目开发的时候,有时候可能需要我们来对页面后退和前进,这个东西跟浏览器自带的前进后退功能很像,下面来大致讲一下在vue中浏览器的前进和后退 一.后退功能 vue中的后退有好多种方法可以使用,使用这些方 ...

  4. 常用代码块:创建httpclient 2

    HttpGet httpGet = new HttpGet(url);SSLContext sslcontext = SSLContexts.custom().loadTrustMaterial(ne ...

  5. 随机生成六位验证码函数版(python)

    import random def code(n=6,alpha=True): s = '' # 创建字符串变量,存储生成的验证码 for i in range(n): # 通过for循环控制验证码位 ...

  6. W5100硬件设计和调试要点

    文章来源:成都浩然 与MCU的接口 W5100与MCU接口採用并行总线方式(假设要使用SPI接口,建议採用W5200),因此W5100与MCU的接口设计相对简单.以AT89C52为例,例如以下图所看到 ...

  7. java.sql.SQLException: The user specified as a definer ('root'@'%') does not exist

    权限问题,授权给 root 所有sql 权限 在Navicat for MySQL中按F6进入命令列界面 mysql> grant all privileges on *.* to root@& ...

  8. 【转】api网关

    微服务之API网关 一.引言 随着互联网的快速发展,当前以步入移动互联.物联网时代.用户访问系统入口也变得多种方式,由原来单一的PC客户端,变化到PC客户端.各种浏览器.手机移动端及智能终端等.同时系 ...

  9. vim之可视化

    参考文档:http://blog.csdn.net/ii1245712564/article/details/46960387 先梳理关键知识,方便查阅 v(小v):进入可视化 V(大V):进入可视行 ...

  10. OC源文件扩展名

    常见的文件扩展名 扩展名 含义 扩展名 含义 .c C语言源文件 .mm Objective-C++源文件 .cc..cpp C++源文件 .pl Perl源文件 .h 头文件 .o Object(编 ...