如果x是列表,为什么x + =“ha”工作,而x = x +“ha”抛出exception?

从我所知道的很less,+列表只需要第二个操作数是可迭代的,这个“哈”显然是。

在代码中:

>>> x = [] >>> x += "ha" >>> x ['h', 'a'] >>> x = x + "ha" Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: can only concatenate list (not "str") to list 

在列表中使用+=就像调用extend ,而不是+

  • 你可以用iterable调用extend
  • 您只能使用+与另一个列表。

我只能猜测为什么做出这个决定,但我认为这是出于性能的原因。 调用+导致创build新的对象,并且复制所有项目,而extend可以使用现有列表对象中的可用空间,在某些情况下可以保存副本。

这个决定的另一个副作用是,如果你写x += y ,对列表的其他引用将会看到改变,但是如果你使用x = x + y那么它们不会。 如下所示:

 >>> x = ['a','b']
 >>> y = ['c',d']
 >>> z = x
 >>> x + = y
 >>> z
 ['A B C D']

 >>> x = ['a','b']
 >>> y = ['c',d']
 >>> z = x
 >>> x = x + y
 >>> z
 ['a','b']

参考

列表的Python源代码 。

+=源代码:

静态PyObject *
 list_inplace_concat(PyListObject * self,PyObject * other)
 {
     PyObject *结果;

     result = listextend (self,other);
    如果(结果== NULL)
        返回结果;
     Py_DECREF(结果);
     Py_INCREF(个体);
    返回(PyObject *)self;
 }

+源代码:

静态PyObject *
 list_concat(PyListObject * a,PyObject * bb)
 {
     Py_ssize_t大小;
     Py_ssize_t我;
     PyObject ** src,** dest;
     PyListObject * np;
     if(!PyList_Check(bb)){
         PyErr_Format(PyExc_TypeError,
                   “只能连接列表(不是\”%。200s \“)列表”,
                   BB-> ob_type-> tp_name);
        返回NULL;
     }

     //等等

你正在考虑这个问题。 你问为什么x = x + 'ha'抛出一个exception,因为x += 'ha'起作用。 真的,问题是为什么x += 'ha'可以工作。

每个人都同意(我希望) 'abc' + 'ha'[1, 2, 3] + ['h', 'a']应该起作用。 在这些情况下,重载+=进行就地修改似乎是合理的。

语言devise者决定[1, 2, 3] + 'ha'不应该,因为你在混合不同的types。 而且这似乎也是合理的。

所以问题是为什么他们决定在x += 'ha'的情况下允许混合不同的types。 在这种情况下,我想有几个原因:

  • 这是一个方便的速记
  • 很明显发生了什么(你把迭代器中的每个项目追加到x

一般来说,Python试图让你做你想做的事情,但是如果有歧义的地方,它往往会迫使你明确。

定义运算符时,有两个不同的“添加”运算符:一个称为__add__ ,另一个称为__add__ __iadd__ 。 后者是用+=原地添加,另一个是正则+运算符。 http://docs.python.org/reference/datamodel.html有更多的信息。;