连接两个列表—'+='和extend()之间的差异

时间:2022-04-26 21:31:43

I've seen there are actually two (maybe more) ways to concatenate lists in Python: One way is to use the extend() method:

我已经看到在Python中有两种(可能更多)方法来连接列表:一种方法是使用extend()方法:

a = [1, 2]
b = [2, 3]
b.extend(a)

the other to use the plus(+) operator:

另使用+(+)运算符:

b += a

Now I wonder: Which of those two options is the 'pythonic' way to do list concatenation and is there a difference between the two (I've looked up the official Python tutorial but couldn't find anything anything about this topic).

现在我想知道:在这两个选项中,哪一个是执行列表连接的“Python”方法,这两个选项之间有区别吗(我查阅了官方的Python教程,但是找不到任何关于这个主题的内容)。

6 个解决方案

#1


158  

The only difference on a bytecode level is that the .extend way involves a function call, which is slightly more expensive in Python than the INPLACE_ADD.

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

It's really nothing you should be worrying about, unless you're performing this operation billions of times. It is likely, however, that the bottleneck would lie some place else.

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

#2


120  

You can't use += for non-local variable (variable which is not local for function and also not global)

不能使用+=来表示非局部变量(变量不是局部变量,也不是全局变量)

def main():
    l = [1, 2, 3]

    def foo():
        l.extend([4])

    def boo():
        l += [5]

    foo()
    print l
    boo()  # this will fail

main()

It's because for extend case compiler will load the variable l using LOAD_DEREF instruction, but for += it will use LOAD_FAST - and you get *UnboundLocalError: local variable 'l' referenced before assignment*

这是因为扩展用例编译器将使用LOAD_DEREF指令加载变量l,而+=将使用LOAD_FAST -您将在赋值前得到*UnboundLocalError:局部变量'l'引用*

#3


18  

You can chain function calls, but you can't += a function call directly:

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

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

#4


12  

According to the Zen of Python:

根据Python的禅宗:

Simple is better than complex.

简单胜于复杂。

b += a is more simple than b.extend(a).

b += a比b.extend(a)简单。

The builtins are so highly optimized that there's no real performance difference.

内置组件是如此高度优化,以至于没有真正的性能差异。

#5


6  

I would say that there is some difference when it comes with numpy (I just saw that the question ask about concatenating two lists, not numpy array, but since it might be a issue for beginner, such as me, I hope this can help someone who seek the solution to this post), for ex.

我会说有一些差异与numpy时(我刚看见这个问题询问连接两个列表,不是numpy数组,但因为它可能是一个问题对于初学者,像我这样的,我希望这可以帮助那些寻求解决这篇文章),交货。

import numpy as np
a = np.zeros((4,4,4))
b = []
b += a

it will return with error

它会带着错误返回

ValueError: operands could not be broadcast together with shapes (0,) (4,4,4)

ValueError:操作数不能与形状一起广播(0,)(4,4,4,4)

b.extend(a) works perfectly

b.extend(a)完美的工作

#6


4  

From python 3.5.2 source code: No big difference.

从python 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;
}

#1


158  

The only difference on a bytecode level is that the .extend way involves a function call, which is slightly more expensive in Python than the INPLACE_ADD.

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

It's really nothing you should be worrying about, unless you're performing this operation billions of times. It is likely, however, that the bottleneck would lie some place else.

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

#2


120  

You can't use += for non-local variable (variable which is not local for function and also not global)

不能使用+=来表示非局部变量(变量不是局部变量,也不是全局变量)

def main():
    l = [1, 2, 3]

    def foo():
        l.extend([4])

    def boo():
        l += [5]

    foo()
    print l
    boo()  # this will fail

main()

It's because for extend case compiler will load the variable l using LOAD_DEREF instruction, but for += it will use LOAD_FAST - and you get *UnboundLocalError: local variable 'l' referenced before assignment*

这是因为扩展用例编译器将使用LOAD_DEREF指令加载变量l,而+=将使用LOAD_FAST -您将在赋值前得到*UnboundLocalError:局部变量'l'引用*

#3


18  

You can chain function calls, but you can't += a function call directly:

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

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

#4


12  

According to the Zen of Python:

根据Python的禅宗:

Simple is better than complex.

简单胜于复杂。

b += a is more simple than b.extend(a).

b += a比b.extend(a)简单。

The builtins are so highly optimized that there's no real performance difference.

内置组件是如此高度优化,以至于没有真正的性能差异。

#5


6  

I would say that there is some difference when it comes with numpy (I just saw that the question ask about concatenating two lists, not numpy array, but since it might be a issue for beginner, such as me, I hope this can help someone who seek the solution to this post), for ex.

我会说有一些差异与numpy时(我刚看见这个问题询问连接两个列表,不是numpy数组,但因为它可能是一个问题对于初学者,像我这样的,我希望这可以帮助那些寻求解决这篇文章),交货。

import numpy as np
a = np.zeros((4,4,4))
b = []
b += a

it will return with error

它会带着错误返回

ValueError: operands could not be broadcast together with shapes (0,) (4,4,4)

ValueError:操作数不能与形状一起广播(0,)(4,4,4,4)

b.extend(a) works perfectly

b.extend(a)完美的工作

#6


4  

From python 3.5.2 source code: No big difference.

从python 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;
}