Python3中的“联动”现象
技术背景
在python中定义一个列表时,我们一定要注意其中的可变对象的原理。虽然python的语法中没有指针,但是实际上定义一个列表变量时,是把变量名指到了一个可变对象上。如果此时我们定义另外一个变量也指到同一个可变对象的话,就会造成一个“联动”的现象。也就是改变其中的一个值时,另一个值也会随之而改变。本文使用的Python版本为Python 3.7.13
测试案例
这里我们先定义一个列表a,然后把这个空的列表a直接赋值给变量b,此时a和b都是一个空的列表:
In [1]: a = []
In [2]: b = a
In [3]: print (a,b)
[] []
那么如果此时我们修改a的值,那么此前被a赋值的变量b是否也会随之改变呢?
In [4]: a.append(1)
In [5]: print (a,b)
[1] [1]
In [6]: a.append(2)
In [7]: print (a,b)
[1, 2] [1, 2]
In [8]: a = [3]
In [9]: print (a,b)
[3] [1, 2]
In [10]: a.append(4)
In [11]: print (a,b)
[3, 4] [1, 2]
从运行结果来看,我们可以发现,当对a先后扩展一个元素1和2时,变量b的值也随之改变,跟a是同步变化的。但是如果把a这个变量名指向一个新的列表上,此时b的值不会发生变化。这就相当于,给变量a赋新的值的时候,变量b指向了a原来的值,而a这个变量名指向了新的数值,此后两者之间的关联就消失了。之所以没有指针定义的python编程语言,会出现这样的情况,就是因为列表类型属于可变参量,所以如果把两个变量指向同一个列表,两个变量的值是会同步的,即使初始的列表不是一个空的列表,结果也是一样的:
In [23]: a = [1]
In [24]: b = a
In [25]: a += [2]
In [26]: print (a,b)
[1, 2] [1, 2]
而且这个同步还是双向的,也就是说,修改a会同步到b,修改b也会同步到a:
In [11]: a = []
In [12]: b = a
In [13]: b.append(5)
In [14]: print (a,b)
[5] [5]
那么除了列表这个数据结构之外,其他类型的数据结构是否存在类似的现象呢?首先用字典类型来测试一下:
In [10]: a = {}
In [11]: b = a
In [12]: print (a,b)
{} {}
In [13]: a[1]=1
In [14]: print (a,b)
{1: 1} {1: 1}
经过测试我们发现,字典也是属于可变参量的类型。除了列表和字典外,其他的就是普通的数值类型和元组Tuple类型,还有一些第三方定义的数据类型,也可以分别测试一下:
In [15]: a = 1
In [16]: b = a
In [17]: a += 1
In [18]: print (a,b)
2 1
In [19]: a = (1,)
In [20]: b = a
In [21]: a += (2,)
In [22]: print (a,b)
(1, 2) (1,)
In [23]: a = '1'
In [24]: b = a
In [25]: a += '2'
In [26]: print (a,b)
12 1
测试结果表明,数值类型和元组类型在“链式”赋值之后,是直接把值给了其他变量的,而不是传递一个指针。但是另一个需要引起重视的是,第三方numpy所定义的array,也是一个可变参量:
In [19]: import numpy as np
In [20]: a = np.array([1], np.float32)
In [21]: b = a
In [22]: print (a,b)
[1.] [1.]
In [23]: a[0] = 2
In [24]: print (a,b)
[2.] [2.]
可以发现,a和b两者的结果也是同步变化的。因为没研究过Python的底层实现,也许区分可变参量和非可变参量的方法,就是看其能不能被哈希?
In [15]: hash(1)
Out[15]: 1
In [16]: hash([1])
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-16-0579e98ca3ee> in <module>
----> 1 hash([1])
TypeError: unhashable type: 'list'
In [17]: hash({'1':1})
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-17-b18acecf6a20> in <module>
----> 1 hash({'1':1})
TypeError: unhashable type: 'dict'
In [18]: hash((1,))
Out[18]: 3430019387558
In [29]: hash(np.array([1.]))
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-29-b9e8d96de6be> in <module>
----> 1 hash(np.array([1.]))
TypeError: unhashable type: 'numpy.ndarray'
In [30]: hash(np.array([1.]).tobytes())
Out[30]: 1211024724661850177
从结果中我们发现,那些可以被哈希的类型都是非可变参量,也就是在“链式赋值”的过程中不会发生“联动”的类型。
总结概要
假如你在Python中初始化了一个变量a的值,然后用a来初始化另一个变量b,此时你希望得到的b的数值是跟a同步变化的,还是独立变化的呢?Python这个编程语言虽然没有指针类型,但是Python中的可变参量也可以像指针一样,改变一个数值之后,所有指向该数值的可变参量都会随之而改变。就比如说改变a的值,会同步的去改变b的值。那么我们应该对这种类型的赋值有所了解,才能够避免在实际的编程中犯错。
版权声明
本文首发链接为:https://www.cnblogs.com/dechinphy/p/syc-note.html
作者ID:DechinPhy
更多原著文章:https://www.cnblogs.com/dechinphy/
请博主喝咖啡:https://www.cnblogs.com/dechinphy/gallery/image/379634.html
Python3中的“联动”现象的更多相关文章
- 【转】Python3中遇到UnicodeEncodeError: 'ascii' codec can't encode characters in ordinal not in range(128)
[转]Python3中遇到UnicodeEncodeError: 'ascii' codec can't encode characters in ordinal not in range(128) ...
- Python3中的字符串函数学习总结
这篇文章主要介绍了Python3中的字符串函数学习总结,本文讲解了格式化类方法.查找 & 替换类方法.拆分 & 组合类方法等内容,需要的朋友可以参考下. Sequence Types ...
- Python3中使用PyMySQL连接Mysql
Python3中使用PyMySQL连接Mysql 在Python2中连接Mysql数据库用的是MySQLdb,在Python3中连接Mysql数据库用的是PyMySQL,因为MySQLdb不支持Pyt ...
- python3 中mlpy模块安装 出现 failed with error code 1的决绝办法(其他模块也可用本方法)
在python3 中安装其它模块时经常出现 failed with error code 1等状况,使的安装无法进行.而解决这个问题又非常麻烦. 接下来以mlpy为例,介绍一种解决此类安装问题的办法. ...
- python3中返回字典的键
我在看<父与子的编程之旅>的时候,有段代码是随机画100个矩形,矩形的大小,线条的粗细,颜色都是随机的,代码如下, import pygame,sys,random from pygame ...
- python3中的zip
在 python2 中zip可以将两个列表并入一个元组列表,如: a = [1,2,3,4] b = [5,6,7,8] c = zip(a,b) 结果:c [(1,5),(2,6),(3,7),(4 ...
- python3中输出不换行
python2中输出默认是换行的,为了抑制换行,是这么做的: print x, 到了python3中,print变成一个函数,这种语法便行不通了.用2to3工具转换了下,变成这样了: print(x, ...
- Python3中的新特性(3)——代码迁移与2to3
1.将代码移植到Python2.6 建议任何要将代码移植到Python3的用户首先将代码移植到Python2.6.Python2.6不仅与Python2.5向后兼容,而且支持Python3中的部分新特 ...
- Python3中的新特性(1)——新的语言特性
1.源代码编码和标识符 Python3假定源代码使用UTF-8编码.另外,关于标识符中哪些字符是合法的规则也放宽了.特别是,标识符可以包含代码点为U+0080及以上的任意有效Unico ...
- python3中socket套接字的编码问题解决
一.TCP 1.tcp服务器创建 #创建服务器 from socket import * from time import ctime #导入ctime HOST = '' #任意主机 PORT = ...
随机推荐
- [转帖]vCenter使用 VMCA 续订证书:续订证书时发生意外错误
https://www.dinghui.org/vcenter-sts-certificate.html 起因:有一处客户vCenter告警:STS签名证书即将过期. 处理办法:系统管理-证书-证书管 ...
- SQLSERVER 通过分离附加的方式迁移文件存储的位置.
有时候 SQLSERVER的数据库所在磁盘满了,或者是性能变的很差, 需要转换一下磁盘的位置. 这个时候最简单的办法是通过分离附加的方式进行处理. 0. 准备工作 0.1 备份-备份-备份 没有备份 ...
- 工单 工序外协 更改PR/PO
工序外协详解介绍'https://blog.csdn.net/weixin_43814706/article/details/113586961' 需求:创建工序委外的工单时更改对应PR/PO 行文本 ...
- runc网络与systemd管理runc应用
1. 创建网络命名空间 ip netns add <ns> # ns是自定义网络空间名 # 例如: ip netns add haproxy # 创建一个给 haproxy使用的网络命名空 ...
- 【K哥爬虫普法】倒计时21天!事关爬虫er们能否平安回家过年!
我国目前并未出台专门针对网络爬虫技术的法律规范,但在司法实践中,相关判决已屡见不鲜,K 哥特设了"K哥爬虫普法"专栏,本栏目通过对真实案例的分析,旨在提高广大爬虫工程师的法律意识, ...
- ClickHouse(08)ClickHouse表引擎概况
目录 合并树家族 日志引擎系列 集成的表引擎 其他特殊的引擎 资料分享 参考文章 目前ClickHouse的表引擎主要有下面四个系列,合并树家族.日志引擎系列.集成的表引擎和其他特殊的引擎. 合并树家 ...
- 若依、vue三级路由缓存失败
router.beforeEach((to, from, next) => { NProgress.start() if (getToken()) { // 三级菜单组件无法缓存问题 if (t ...
- 4.0 Python 变量与作用域
在python中,变量的作用域决定了变量在哪些位置可以被访问.一个程序中的变量并不是所有的地方都可以访问的,其访问权限决定于变量的赋值位置.python中有两种最基本的变量作用域:局部作用域和全局作用 ...
- centos6.5安装MongoDB4.4.23
前言 1.目前MongoDB最新稳定版本是:6.0.8 2.MongoDB 5+和6+版本已不支持centos6.2+系统,参考https://docs.mongoing.com/install-mo ...
- 【可观测性系列】 OpenTelemetry Collector的部署模式分析
作者简介:大家好,我是蓝胖子 ️博客首页:主页蓝胖子的编程梦 ️热门专题:我的服务监控实践 ,500行代码手写Docker **每日一句:白日莫闲过,青春不再来 大家好,我是蓝胖子,在前面我介绍了下O ...