增量赋值运算符有 += 和 *=。+= 背后的特殊方法是 __iadd__,如果一个类没有实现 __iadd__ 方法,Python 会退一步调用 __add__ 方法。这两个方法的区别在于,__iadd__ 为就地改动,不会改变原值的内存地址,而 __add__ 方法会得到一个新对象。

考虑下面一个表达式:

  a += b

如果 a 实现了 __iadd__ 方法,a 会就地改动(内存地址不变)。如果 a 没有实现 __iadd__ 方法,那么 a += b 这个表达式的效果就变得跟 a = a + b 一样了,生成一个新的对象赋给 a。

总体来讲,可变序列一般都实现了 __iadd__ 方法,因此 += 是就地加法,而不可变序列根本就不支持这个操作。

*= 和 += 一样,只是背后的特殊方法为 __imul__。

a = [1, 2, 3]
b = [4, 5, 6]
print("id(a) = %d" % id(a))
a += b
print("id(a) = %d" % id(a)) c = [1, 2, 3]
print("id(c) = %d" % id(c))
c = c + b
print("id(c) = %d" % id(c)) d = (1, 2, 3)
print("id(d) = %d" % id(d))
d *= 2
print("id(d) = %d" % id(d))

运行结果如下:

id(a) = 1298277978824
id(a) = 1298277978824
id(c) = 1298277978696
id(c) = 1298277978632
id(d) = 1298277972872
id(d) = 1298277136616

了解了序列的增量赋值,我们来看 Leonardo Rochael 在 2013 年的 Python 巴西会议上提到的谜题:

t = (1, 2, [30, 40])
t[2] += [50, 60]

A. t 变成 (1, 2, [30, 40, 50, 60])

B. 因为 tuple 不支持对它的元素赋值,所以会抛出 TypeError 异常

C. 以上两个都不是

D. A 和 B 都是对的

估计很多人会跟我一样选 B,但其实答案是 D。在控制台运行代码,显示结果如下:

总结:

1、对不可变序列进行重复拼接操作的话,效率会很低,因为每次都要新建一个序列,然后把原来序列中的元素复制到新的序列里,然后再追加新的元素。

2、不要把可变对象放在元组里面。

3、增量赋值不是一个原子操作,我们刚才也看到了,它虽然抛出了异常,但 t 的值还是改变了。

Python:序列的增量赋值的更多相关文章

  1. 关于python中的增量赋值的理解

    增量赋值运算符 += 和 *= 的表现取决于它们的第一个操作对象 += 操作首先会尝试调用对象的 __ iadd__方法,如果没有该方法,那么尝试调用__add__方法,所以+= 与 + 的区别实质是 ...

  2. python学习记录20190122_增量赋值

    python中的增量赋值 一,在python中a=a+b和a+=b有区别吗 **1,对可变的数据类型 a=[1,2,3]print(id(a)) #1602469350792b=[4,5]a=a+bp ...

  3. 流畅的python python 序列

    内置序列 容器类型 list .tuple和collections.deque这些序列能放入不同的类型的数据 扁平序列 str.byets.bytearray.memoryview(内存视图)和arr ...

  4. Python序列构成的数组

    1.内置序列类型 容器序列:list,tuple,collections.deque (能存放不同类型) 扁平序列:str,bytes,bytearray,memoryview,array.array ...

  5. [Python笔记][第二章Python序列-tuple,dict,set]

    2016/1/27学习内容 第二章 Python序列-tuple tuple创建的tips a_tuple=('a',),要这样创建,而不是a_tuple=('a'),后者是一个创建了一个字符 tup ...

  6. [python笔记][第二章Python序列-list]

    2016/1/27学习内容 第二章 Python序列-list list常用操作 list.append(x) list.extend(L) list.insert(index,x) list.rem ...

  7. python变量和变量赋值的几种形式

    动态类型的语言 python是动态类型的语言,不需要声明变量的类型. 实际上,python中的变量仅仅只是用来保存一个数据对象的地址.无论是什么数据对象,在内存中创建好数据对象之后,都只是把它的地址保 ...

  8. [Python笔记][第二章Python序列-复杂的数据结构]

    2016/1/27学习内容 第二章 Python序列-复杂的数据结构 堆 import heapq #添加元素进堆 heapq.heappush(heap,n) #小根堆堆顶 heapq.heappo ...

  9. python学习笔记:python序列

    python序列包括字符串.列表和元组三部分,下面先总的说一下python序列共有的一些操作符和内建函数. 一.python序列 序列类型操作符 标准类型的操作符一般都能适用于所有的序列类型,这里说一 ...

随机推荐

  1. index_levedb.go

    )     binary.BigEndian.PutUint64(key, fid)     return l.db.Delete(key, nil) } //关闭资源 func (l *LevelD ...

  2. BZOJ_3239_Discrete Logging_BSGS

    BZOJ_3239_Discrete Logging_BSGS 题意:Given a prime P, 2 <= P < 231, an integer B, 2 <= B < ...

  3. BZOJ_5301_[Cqoi2018]异或序列&&CF617E_莫队

    Description 已知一个长度为 n 的整数数列 a[1],a[2],…,a[n] ,给定查询参数 l.r ,问在 [l,r] 区间内,有多少连续子 序列满足异或和等于 k . 也就是说,对于所 ...

  4. BZOJ_3174_[Tjoi2013]拯救小矮人_贪心+DP

    BZOJ_3174_[Tjoi2013]拯救小矮人_贪心+DP Description 一群小矮人掉进了一个很深的陷阱里,由于太矮爬不上来,于是他们决定搭一个人梯.即:一个小矮人站在另一小矮人的 肩膀 ...

  5. gitlab-ci-runner安装

    前言 什么是CI/CD? CI (Continuous Integration) 持续集成, CD (Continuous Delivery) 持续部署 个人理解 本地开发代码, 提交远程仓库 仓库接 ...

  6. Android 7.0 存储系统—Vold与MountService分析(二)(转 Android 9.0 分析)

    Android的存储系统(二) 回顾:前贴主要分析了Android存储系统的架构和原理图,简要的介绍了整个从Kernel-->Vold-->上层MountService之间的数据传输流程, ...

  7. 神奇的Scala Macro之旅(四)- BeanBuilder

    在Java开发中,经常会有一个需求,将一个 Bean 复制到另外一个 Bean,尤其是在后台分层的场景下,在不同的层之间传递信息,经常需要进行 这样的一个对象复制工作,类似于: val source: ...

  8. Failed to fetch URL http://dl-ssl.google.com/android/repository/addons_list-2.xml, reason:

    http://blog.csdn.net/gyming/article/details/8168166/ 最近接受的这个项目需要Android SDK Tools revision 22.6.2 or ...

  9. 死磕 java集合之ConcurrentSkipListSet源码分析——Set大汇总

    问题 (1)ConcurrentSkipListSet的底层是ConcurrentSkipListMap吗? (2)ConcurrentSkipListSet是线程安全的吗? (3)Concurren ...

  10. java提高(15)---java深浅拷贝

    #java深浅拷贝 一.前言 为什么会有深浅拷贝这个概念? 我觉得主要跟JVM内存分配有关,对于基本数据类型,只存在栈内存,所以它的拷贝不存在深浅拷贝这个概念.而对于对象而言,一个对象的创建会在内存中 ...