看来,在 Python 中,list += x
适用于任何可迭代的x
:
In [6]: l = []
In [7]: l += [1]
In [8]: l += (2, 3)
In [9]: l += xrange(5)
In [10]: l
Out[10]: [1, 2, 3, 0, 1, 2, 3, 4]
这种行为是否记录在任何地方?
与 相比list + x
,后者仅在x
也是 a时才有效list
。这在文档中有详细说明。
看来,在 Python 中,list += x
适用于任何可迭代的x
:
In [6]: l = []
In [7]: l += [1]
In [8]: l += (2, 3)
In [9]: l += xrange(5)
In [10]: l
Out[10]: [1, 2, 3, 0, 1, 2, 3, 4]
这种行为是否记录在任何地方?
与 相比list + x
,后者仅在x
也是 a时才有效list
。这在文档中有详细说明。
它的工作方式与它相同,
.extend()
只是它也返回self
. 我找不到解释这一点的文档。:-(
以下是取自的相关源代码listobject.c
:
list_inplace_concat(PyListObject *self, PyObject *other)
{
PyObject *result;
result = listextend(self, other);
if (result == NULL)
return result;
Py_DECREF(result);
Py_INCREF(self);
return (PyObject *)self;
}
我提出了一个错误报告以修复文档:http: //bugs.python.org/issue16701
它现在记录在 Python 3.4+ 和 Python 2.7 中:
4.6.3. 可变序列类型
下表中的操作是在可变序列类型上定义的。提供
collections.abc.MutableSequence
ABC 是为了更容易在自定义序列类型上正确实现这些操作。[Below]
s
是可变序列类型的一个实例,t
是任何可迭代的对象,并且x
是满足任何类型和值限制的任意对象s
(例如,bytearray
只接受满足值限制的整数0 <= x <= 255
)。
s.extend(t)
或者s += t
扩展
s
内容t
(大部分与 相同s[len(s):len(s)] = t
)
因此,现在有文件证明,对于任何可变序列类型s
,s += t
都是s.extend(t)
.
不(Guido 确认;感谢 Ashwini Chaudhary)。for 序列的行为+=
通常是未指定的。我得出的结论是,规范不要求x + y
wherex
是一个列表,并且y
其他一些可迭代是一个错误(因此其他实现可以选择允许它),并且其他实现可以限制+=
为需要同质操作数。
但是,不这样做的原因很明显:python 通常会尝试对操作数做正确的事情,而不是要求严格的类型相等。真正的谜团是为什么列表不允许异类添加。
更新:我从来没有真正考虑过非同质加法问题,主要是因为itertools.chain
它几乎是该问题的完整解决方案。
欢迎那些更熟悉 Python 内部的人发表评论,以解释为什么需要同质加法。(这里的问题:为什么Python列表加法必须是同质的?)
对于那里的性能怪胎,是+=
的,比extend
:
>>> from timeit import repeat
>>> min(repeat('a.extend((1,2,3,4,5,6,7))', 'a=[]'))
0.23489440699995612
>>> min(repeat('e((1,2,3,4,5,6,7))', 'a=[]; e = a.extend'))
0.2214308570000867
>>> min(repeat('a+=(1,2,3,4,5,6,7)', 'a=[]'))
0.21909333300027356
以下是它的比较方式append
:
>>> min(repeat('a.append(1)', 'a=[]'))
0.062107428999297554
>>> min(repeat('p(1)', 'a=[]; p = a.append'))
0.04968810399986978
>>> min(repeat('a+=(1,)', 'a=[]'))
0.0501599309991434
(在 Python 3.7 64 位、Windows 上测试)