Python序列的增量赋值+= *=

本文探讨Python中的增量赋值运算符`+=`和`*=`,尤其是它们在可变序列上的行为。当应用于不可变序列如元组时,这些运算符会导致新的对象生成,效率较低。对于可变序列(如列表),`+=`通过`__iadd__`实现就地加法,相当于`extend()`。而`*=`则对应`__imul__`。文章通过一个谜题展示了当尝试对元组的可变元素进行增量赋值时,虽然会抛出异常,但实际操作已完成,提醒开发者避免将可变对象放入元组中。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

增量赋值运算符 +=和*=   一般作用于可变序列上

如果对于不可变序列(如tuple), 每次都会生成一个新的对象,效率就很低。

 

+= 对应的方法__iadd__就地加法。如果一个类没有实现,python会退一步调用__add__

a +=b

以上实例中,如果a实现了__iadd__方法,对于可变序列(list、bytearray、array.array)来说,a会就地改动,等于调用了a.extend(b)。

如果没有实现__iadd__就是等于a = a+b 先计算a+b等到一个新的对象,赋值给a

 

*= 对应的方法__imul__,原理同上

 

一个+=的谜题

以下是2013 python巴西会议中,有人提出这个谜题

>>> t = (1,2,[20,30])

>>> t[2] += [40, 50]

Traceback (most recent call last):

 File "<stdin>", line 1, in <module>

TypeError: 'tuple' object does not support item assignment

>>> t

(1, 2, [20, 30, 40, 50])

 

以上代码看出来,t[2]被改动了,但是也有异常抛出,因为t是元祖,不支持对他的元素赋值。

 

如果分析字节码,可以得出以下步骤,解析了以上现象:

  1. t[2]的值存入TOS(TOP Of Stack 栈的顶端)
  2. 计算TOS +=[40, 50],这一步可以完成没有报错,因为TOS是指向的一个可变对象 列表
  3. t[2] = TOS 赋值操作,这里就会报错,因为t是不可变的元祖,

image.png

 

 

以上操作的教训:

  1. 不要把可变对象放到元祖中。
  2. 增量赋值不是原子操作,虽然抛出了异常,但是还是完成增量操作
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值