python序列对象使用+和*和*=和+=


目录
  • python中+和*
  • 含有可变元素的容器序列对象不可用*
  • 对于上边例子,正确做法是用列表推导式:
  • 序列增量赋值 *= 和 +=

python中+和*

python中序列都支持 + 和 * 操作。

  • + 拼接两个序列,返回拼接后的序列
  • * 将一个序列复制几份,然后拼接
  • + 和 * 都不改变原有序列对象。

含有可变元素的容器序列对象不可用*

因为容器序列中保存的是元素的引用,如果直接用 * 复制容器对象再拼接,则会得到几份相同的引用。如下边例子。

对于上边例子,正确做法是用列表推导式:

此时因为容器序列对象['_']中只有一个元素,该元素是字符串,因此元素不可变,故可以用 *

序列增量赋值 *= 和 +=

以+=为例讲解,*=类似。

a += b
  • +=背后是调用的特殊方法__iadd__,该方法用于就地加法。如果类中没有实现__iadd__,则调用__add__。
  • 如果实现了__iadd__,且a为可变序列,则把b复制一份接到a上,对a进行原地改动。效果等价于a.extend(b)。
  • 如果没有实现__iadd__,则a += b等价于a = a + b,会先计算a + b生成一个新的对象,然后赋值给a。此时变量名a已经被关联到了新的对象。
  • 如果a为不可变序列,不支持该操作。
  • *=对应的特殊方法是__imul__。
  • 一般对不可变序列进行重复拼接操作效率很低,因为需要构造新对象,但是str是个例外,因为字符串+=操作太普遍,因此CPython进行了优化,为str对象初始化内存的时候预留了可扩展空间。