Python 笔试集:什么时候 i = i + 1 并不等于 i += 1?
增强型赋值语句是经常被使用到的,因为从各种学习渠道中,我们能够得知 i += 1 的效率往往要比 i = i + 1 更高一些(这里以 += 为例,实际上增强型赋值语句不仅限于此)。所以我们会乐此不疲的在任何能够替换普通赋值语句的地方使用增量型赋值语句,以此来优化代码。那么我们是否有想过,在什么情况下 i += 1 其实并不等效于 i = i + 1 !!
例一:使用增强型赋值语句:
In [1]: a = [1, 2, 3]
In [2]: b = a
In [3]: b += [1, 2, 3]
In [4]: print a, b
[1, 2, 3, 1, 2, 3] [1, 2, 3, 1, 2, 3]
In [5]: id(a), id(b)
Out[5]: (140213762276096, 140213762276096)
例二:使用普通赋值语句:
In [6]: a = [1, 2, 3]
In [7]: b = a
In [8]: b = b + [1, 2, 3]
In [9]: print a, b
[1, 2, 3] [1, 2, 3, 1, 2, 3]
In [10]: id(a), id(b)
Out[10]: (140213762466232, 140213762276168)
上述两个例子中,将一个列表类型对象赋值给变量 a,再将变量 a 赋值给变量 b,此时 a、b 指向了同一个内存对象 [1, 2, 3]。然后分别应用增量赋值运算符和普通赋值运算符来操作变量 b。从最后的结果来看,例一中的 a、b 在进行运算后依旧指向了同一个内存对象。例二则相反,a、b 分别指向了不同的内存对象,也就是说在例二中隐式的新建了一个内存对象。
这是一个值得注意的坑,警惕我们在使用增量赋值运算符来操作可变对象(如:列表)时可能会产生不可预测的结果。
要解释这个问题,首先需要了解「Python 共享引用」的概念:在 Python 中,允许若干个不同的变量引用指向同一个内存对象。同时在前文中也提到,增强赋值语句比普通赋值语句的效率更高,这是因为在 Python 源码中, 增强赋值比普通赋值多实现了“写回”的功能,也就是说增强赋值在条件符合的情况下(例如:操作数是一个可变类型对象)会以追加的方式来进行处理,而普通赋值则会以新建的方式进行处理。这一特点导致了增强赋值语句中的变量对象始终只有一个,Python 解析器解析该语句时不会额外创建出新的内存对象。所以例一中变量 a、b 的引用在最后依旧指向了同一个内存对象;相反,对于普通赋值运算语句,Python 解析器无法分辨语句中的两个同名变量(例如:b = b + 1)是否应该为同一内存对象,所以干脆再创建出一个新的内存对象用来存放最后的运算结果,所以例二中的 a、b 从原来指向同一内存对象,到最后分别指向了两个不同的内存对象。
这是一个不为人所熟知的问题,我们能得到的结论就是:尽量不要使用增量赋值运算符来处理任何可变类型对象,除非你对上述问题有了足够的了解。
Python 笔试集:什么时候 i = i + 1 并不等于 i += 1?的更多相关文章
- Python 笔试集(4):True + True == ?
目录 目录 前文列表 面试题True Ture 布尔值 布尔类型是特殊的整数类型 前文列表 Python 笔试集:什么时候 i = i + 1 并不等于 i += 1? Python 笔试集(1):关 ...
- Python 笔试集(3):编译/解释?动态/静态?强/弱?Python 是一门怎样的语言
面试题 解释/编译?动态/静态?强/弱?Python 到底是一门怎样的语言? 编译 or 解释? 编译.解释都是指将(与人类亲和的)编程语言翻译成(计算机能够理解的)机器语言(Machine code ...
- Python 笔试集(2):你不知道的 Python 整数
面试题 分别给出下述代码在终端(e.g. IPyhon)中和在程序中的运行结果: a = 256 b = 256 c = 257 d = 257 def foo(): e = 257 f = 257 ...
- Python 笔试集(1):关于 Python 链式赋值的坑
前言 Python 的链式赋值是一种简易型批量赋值语句,一行代码即可为多个变量同时进行赋值. 例如: x = y = z = 1 链式赋值是一种非常优雅的赋值方式,简单.高效且实用.但同时它也是一个危 ...
- 『Python题库 - 填空题』151道Python笔试填空题
『Python题库 - 填空题』Python笔试填空题 part 1. Python语言概述和Python开发环境配置 part 2. Python语言基本语法元素(变量,基本数据类型, 基础运算) ...
- 机器学习基础:(Python)训练集测试集分割与交叉验证
在上一篇关于Python中的线性回归的文章之后,我想再写一篇关于训练测试分割和交叉验证的文章.在数据科学和数据分析领域中,这两个概念经常被用作防止或最小化过度拟合的工具.我会解释当使用统计模型时,通常 ...
- 通过python构建集中式的病毒扫描机制
Clam AntiVirus(Clam AV)是一个免费而且开放源码的防毒软件,软件与病毒库的更新由开源社区免费发布,目前ClamdAV主要为Linux.Uinux系统提供病毒扫描查杀pyClamad ...
- 实现Redis Cluster并实现Python链接集群
目录 一.Redis Cluster简单介绍 二.背景 三.环境准备 3.1 主机环境 3.2 主机规划 四.部署Redis 4.1 安装Redis软件 4.2 编辑Redis配置文件 4.3 启动R ...
- Python python 数据类型--集
# set 集 '''Python还包括集合的数据类型.集合是无序集合,没有重复元素. 基本用途包括成员资格测试和消除重复条目. 集合对象还支持数学运算,如并集,交集,差异和对称差异. ''' nam ...
随机推荐
- 剑指offer-顺序打印二叉树节点(系列)-树-python
转载自 https://blog.csdn.net/u010005281/article/details/79761056 非常感谢! 首先创建二叉树,然后按各种方式打印: class treeNo ...
- sublime3故障收集emmet无法安装pyv8
本文主要介绍Sublime Text如何开启debug模式,分析使用过程中一些常见错误情形的解决方法.情形一:Package Control:There are no packages availab ...
- node搭建个人博客promise警告解除
警告 (node:8500) UnhandledPromiseRejectionWarning: undefined (node:8500) UnhandledPromiseRejectionWarn ...
- 简单的物流项目实战,WPF的MVVM设计模式(五)
开始界面 <Grid> <Grid.RowDefinitions> <RowDefinition/> <RowDefinition/> <RowD ...
- JS中对数组元素进行增、删、改、查的方法,以及其他方法
前言 昨天联调一个页面,看着就一个页面,接口倒是不少. 热点问题配置测试联调完成(同步异步接口共11个) 1.配置新增 2.配置编辑 3.配置删除 4.热点问题新增 5.热点问题编辑 6.热点问题删除 ...
- JavaEE高级-MyBatisPlus学习笔记
第 1 章 简介 1.1 MyBatisPlus 介绍 -MyBatis-Plus(简称 MP),是一个 MyBatis 的增强工具包,只做增强不做改变. 为简化开发工作.提高生产率而生我们的愿景是成 ...
- python的java胶水(jpype1)
1.直接使用pip安装jpype1 命令 pip install jpype1 但是,很不幸,提示报错,缺少VC++组件. 2.使用其他方法安装 在 https://www.lfd.uci.edu/ ...
- 计蒜客 蓝桥模拟 H. 封印之门
Floyd算法,最短路,判断a,b是否相等. 代码: #include <cstdio> #include <cstdlib> #include <cstring> ...
- 10年前文章_解决parted 编译出错问题
找到 include/site/i386-linux 文件,修改定义ac_cv_sizeof_off_t 的长度,从原来的4改为8 ac_cv_sizeof_off_t=8 删除 build_dir/ ...
- java Byte源码分析
源码: public static int toUnsignedInt(byte x) { return ((int) x) & 0xff; } 原理: -128(byte) 原码:10000 ...