​​增强型赋值语句是经常被使用到的,因为从各种学习渠道中,我们能够得知 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?的更多相关文章

  1. Python 笔试集(4):True + True == ?

    目录 目录 前文列表 面试题True Ture 布尔值 布尔类型是特殊的整数类型 前文列表 Python 笔试集:什么时候 i = i + 1 并不等于 i += 1? Python 笔试集(1):关 ...

  2. Python 笔试集(3):编译/解释?动态/静态?强/弱?Python 是一门怎样的语言

    面试题 解释/编译?动态/静态?强/弱?Python 到底是一门怎样的语言? 编译 or 解释? 编译.解释都是指将(与人类亲和的)编程语言翻译成(计算机能够理解的)机器语言(Machine code ...

  3. Python 笔试集(2):你不知道的 Python 整数

    面试题 分别给出下述代码在终端(e.g. IPyhon)中和在程序中的运行结果: a = 256 b = 256 c = 257 d = 257 def foo(): e = 257 f = 257 ...

  4. Python 笔试集(1):关于 Python 链式赋值的坑

    前言 Python 的链式赋值是一种简易型批量赋值语句,一行代码即可为多个变量同时进行赋值. 例如: x = y = z = 1 链式赋值是一种非常优雅的赋值方式,简单.高效且实用.但同时它也是一个危 ...

  5. 『Python题库 - 填空题』151道Python笔试填空题

    『Python题库 - 填空题』Python笔试填空题 part 1. Python语言概述和Python开发环境配置 part 2. Python语言基本语法元素(变量,基本数据类型, 基础运算) ...

  6. 机器学习基础:(Python)训练集测试集分割与交叉验证

    在上一篇关于Python中的线性回归的文章之后,我想再写一篇关于训练测试分割和交叉验证的文章.在数据科学和数据分析领域中,这两个概念经常被用作防止或最小化过度拟合的工具.我会解释当使用统计模型时,通常 ...

  7. 通过python构建集中式的病毒扫描机制

    Clam AntiVirus(Clam AV)是一个免费而且开放源码的防毒软件,软件与病毒库的更新由开源社区免费发布,目前ClamdAV主要为Linux.Uinux系统提供病毒扫描查杀pyClamad ...

  8. 实现Redis Cluster并实现Python链接集群

    目录 一.Redis Cluster简单介绍 二.背景 三.环境准备 3.1 主机环境 3.2 主机规划 四.部署Redis 4.1 安装Redis软件 4.2 编辑Redis配置文件 4.3 启动R ...

  9. Python python 数据类型--集

    # set 集 '''Python还包括集合的数据类型.集合是无序集合,没有重复元素. 基本用途包括成员资格测试和消除重复条目. 集合对象还支持数学运算,如并集,交集,差异和对称差异. ''' nam ...

随机推荐

  1. HDU1688-POJ3463-Sightseeing(求次短路的条数)

    题意 求出最短路和次短路的条数,当次短路比最短路长度小1时,输出条数之和,反之输出最短路条数. 题解  dis1[],cnt1[],dis2[],cnt2[] 分别表示最短路的长度和条数,次短路的长度 ...

  2. .net WebApi使用swagger 美化接口文档

    本文将一步步演示如何用swagger美化WebApi接口文档,为接口文档添加接口名称说明,为请求参数和返回数据结构字段含义添加注释说明 一.为WebApi项目安装Swagger 首先我们新建一个Web ...

  3. 使用ajax发送文件的三种方式及预览图片的方法,上传按钮美化

    后端代码 def upload(request): if request.method == "GET": return render(request,'upload.html') ...

  4. 前端开发HTML&css入门——CSS&选择器练习

    CSS 层叠样式表 (Cascading Style Sheets)css可以用来为网页创建样式表,通过样式表可以对网页进行装饰.所谓层叠,可以将整个网页想象成是一层一层的结构,层次高的将会覆盖层次低 ...

  5. python中的Tkinter模块

    Tkinter模块("Tk 接口")是Python的标准Tk GUI工具包的接口.Tk和Tkinter可以在大多数的Unix平台下使用,同样可以应用在Windows和Macinto ...

  6. Python爬虫之urllib.parse详解

    Python爬虫之urllib.parse 转载地址 Python 中的 urllib.parse 模块提供了很多解析和组建 URL 的函数. 解析url 解析url( urlparse() ) ur ...

  7. 实现自己的BeanFactory、AOP以及声明式事务

    实现自己的BeanFactory                                                                   在使用spring时,我们很少用& ...

  8. jupyter notebook添加环境

    列出当前kernel: jupyter kernelspec list 删除已有环境:jupyter kernelspec remove NAME 安装新kernel ipython kernel i ...

  9. 10年前文章_respin 下制作iso 文件的脚本说明

    1.prepare_spin.sh 用于在 /var/rpm 下生成  lhs-local 需要的repositery 2.respin.sh 使用revisor 生成 iso 3. post_spi ...

  10. CSS3——制作人物走路的小动画

    一个很简单的小动画,但是还挺有意思的,就是找这种图片很麻烦,我这里把我找的一张图片贴上来,这张图片是我在网上找的,又改了背景色和大小. <!DOCTYPE html> <html l ...