我看到在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;
}

其他回答

列表上的.extend()方法适用于任何可迭代对象*,+=适用于某些可迭代对象,但可能会变得古怪。

import numpy as np

l = [2, 3, 4]
t = (5, 6, 7)
l += t
l
[2, 3, 4, 5, 6, 7]

l = [2, 3, 4]
t = np.array((5, 6, 7))
l += t
l
array([ 7,  9, 11])

l = [2, 3, 4]
t = np.array((5, 6, 7))
l.extend(t)
l
[2, 3, 4, 5, 6, 7]

Python 3.6 *非常确定.extend()适用于任何可迭代对象,但如果我不正确,请评论

修改:"extend()"改为"列表上的.extend()方法" 注:David M. Helmuth的评论很清晰。

来自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;
}

你可以链式调用函数,但你不能直接+=函数调用:

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'在赋值之前引用*

字节码级别上的唯一区别是.extend方式涉及到一个函数调用,在Python中这比INPLACE_ADD方法稍微昂贵一些。

这真的没什么好担心的,除非你做了几十亿次这个操作。然而,瓶颈很可能存在于其他地方。