如果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有更多的信息。;