我看到在Python中实际上有两种(可能更多)方法来连接列表:
一种方法是使用extend()方法:
a = [1, 2]
b = [2, 3]
b.extend(a)
另一个使用加号(+)运算符:
b += a
现在我想知道:这两个选项中哪一个是“python”的方式来做列表连接,两者之间有区别吗?(我已经查阅了官方的Python教程,但找不到任何关于这个主题的任何东西)。
我看到在Python中实际上有两种(可能更多)方法来连接列表:
一种方法是使用extend()方法:
a = [1, 2]
b = [2, 3]
b.extend(a)
另一个使用加号(+)运算符:
b += a
现在我想知道:这两个选项中哪一个是“python”的方式来做列表连接,两者之间有区别吗?(我已经查阅了官方的Python教程,但找不到任何关于这个主题的任何东西)。
当前回答
来自CPython 3.5.2源代码: 差别不大。
static PyObject *
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;
}
其他回答
来自CPython 3.5.2源代码: 差别不大。
static PyObject *
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;
}
当列表在元组中时,只能使用.extend()
这是可行的
t = ([],[])
t[0].extend([1,2])
而这个不会
t = ([],[])
t[0] += [1,2]
原因是+=生成了一个新对象。如果你看一下长版本:
t[0] = t[0] + [1,2]
你可以看到这会改变元组中的对象,这是不可能的。使用.extend()修改元组中的对象,这是允许的。
你可以链式调用函数,但你不能直接+=函数调用:
class A:
def __init__(self):
self.listFoo = [1, 2]
self.listBar = [3, 4]
def get_list(self, which):
if which == "Foo":
return self.listFoo
return self.listBar
a = A()
other_list = [5, 6]
a.get_list("Foo").extend(other_list)
a.get_list("Foo") += other_list #SyntaxError: can't assign to function call
对于非局部变量(对于函数来说不是局部变量,也不是全局变量)不能使用+=
def main():
l = [1, 2, 3]
def foo():
l.extend([4])
def boo():
l += [5]
foo()
print l
boo() # this will fail
main()
这是因为对于扩展情况编译器将使用LOAD_DEREF指令加载变量l,但对于+=它将使用LOAD_FAST -并且你得到*UnboundLocalError:局部变量'l'在赋值之前引用*
实际上,ADD、INPLACE_ADD和extend这三个选项是有区别的。前者总是比较慢,而其他两种大致相同。
有了这些信息,我宁愿使用extend,它比ADD快,而且在我看来,它比INPLACE_ADD更能清楚地说明您在做什么。
试几次下面的代码(适用于Python 3):
import time
def test():
x = list(range(10000000))
y = list(range(10000000))
z = list(range(10000000))
# INPLACE_ADD
t0 = time.process_time()
z += x
t_inplace_add = time.process_time() - t0
# ADD
t0 = time.process_time()
w = x + y
t_add = time.process_time() - t0
# Extend
t0 = time.process_time()
x.extend(y)
t_extend = time.process_time() - t0
print('ADD {} s'.format(t_add))
print('INPLACE_ADD {} s'.format(t_inplace_add))
print('extend {} s'.format(t_extend))
print()
for i in range(10):
test()
ADD 0.3540440000000018 s
INPLACE_ADD 0.10896000000000328 s
extend 0.08370399999999734 s
ADD 0.2024550000000005 s
INPLACE_ADD 0.0972940000000051 s
extend 0.09610200000000191 s
ADD 0.1680199999999985 s
INPLACE_ADD 0.08162199999999586 s
extend 0.0815160000000077 s
ADD 0.16708400000000267 s
INPLACE_ADD 0.0797719999999913 s
extend 0.0801490000000058 s
ADD 0.1681250000000034 s
INPLACE_ADD 0.08324399999999343 s
extend 0.08062700000000689 s
ADD 0.1707760000000036 s
INPLACE_ADD 0.08071900000000198 s
extend 0.09226200000000517 s
ADD 0.1668420000000026 s
INPLACE_ADD 0.08047300000001201 s
extend 0.0848089999999928 s
ADD 0.16659500000000094 s
INPLACE_ADD 0.08019399999999166 s
extend 0.07981599999999389 s
ADD 0.1710910000000041 s
INPLACE_ADD 0.0783479999999912 s
extend 0.07987599999999873 s
ADD 0.16435900000000458 s
INPLACE_ADD 0.08131200000001115 s
extend 0.0818660000000051 s