python关于+=的陷阱

看下面代码

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

我们知道tuple元组是个不可变元素,所以更改元组的元素道理上是不行的,但是我改变的元素是个列表,它本身是可变的,这样可行吗??

先别去控制台运行,猜是下面哪一种:

  1. t 变成 (1, 2, [30, 40, 50, 60])。
  2. 因为 tuple 不支持对它的元素赋值,所以会抛出 TypeError 异常。
  3. 以上两个都不是。
  4. a 和 b 都是对的。

\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\

\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
答案是第四种情况

我们使用Python Tutor(http://www.pythontutor.com)对执行代码进行可视化
在这里插入图片描述在这里插入图片描述
最后我们看看背后的字节码是怎么执行s[a] += b这种操作的
在这里插入图片描述到1是将 s[a] 的值存入 TOS(Top Of Stack,栈的顶端)
到2是计算 TOS += b。这一步能够完成,是因为 TOS 指向的是一个可变对象
到3是s[a] = TOS 赋值。这一步失败,是因为 s 是不可变的元组

所以才会出现即操作成功又报异常的现象

教训:

  1. 不要把可变对象放在元组里面
  2. 增量赋值不是一个原子操作(从字节码可以看出经过了若干步)
©️2020 CSDN 皮肤主题: 技术黑板 设计师:CSDN官方博客 返回首页