Python 连接两个列表 - '+=' 和 extend() 之间的区别
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3653298/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Concatenating two lists - difference between '+=' and extend()
提问by helpermethod
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).
现在我想知道:这两个选项中的哪一个是进行列表连接的“pythonic”方式,两者之间是否有区别(我已经查找了官方 Python 教程,但找不到任何有关此主题的信息)。
采纳答案by SilentGhost
The only difference on a bytecode level is that the .extendway 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.
除非您执行此操作数十亿次,否则您真的无需担心。然而,瓶颈很可能位于其他地方。
回答by monitorius
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 extendcase compiler will load the variable lusing LOAD_DEREFinstruction, but for += it will use LOAD_FAST- and you get *UnboundLocalError: local variable 'l' referenced before assignment*
这是因为对于扩展案例编译器将l使用LOAD_DEREF指令加载变量,但对于 += 它将使用LOAD_FAST- 你得到*UnboundLocalError: local variable 'l' referenced before assignment*
回答by isarandi
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
回答by Lance Ruo Zhang
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) 一起广播
b.extend(a)works perfectly
b.extend(a)完美运行
回答by VicX
From the CPython 3.5.2 source code: No big difference.
来自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;
}
回答by littlebear333
According to the Python for Data Analysis.
根据用于数据分析的 Python。
“Note that list concatenation by addition is a comparatively expensive operation since a new list must be created and the objects copied over. Using extend to append elements to an existing list, especially if you are building up a large list, is usually preferable. ” Thus,
“请注意,通过加法连接列表是一项相对昂贵的操作,因为必须创建新列表并复制对象。使用扩展将元素附加到现有列表中,尤其是在构建大型列表时,通常更可取。“ 因此,
everything = []
for chunk in list_of_lists:
everything.extend(chunk)
is faster than the concatenative alternative:
比串联替代方案更快:
everything = []
for chunk in list_of_lists:
everything = everything + chunk
回答by grofte
extend() works with any iterable*, += works with some but can get funky.
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
*pretty sure .extend() works with any iterable but please comment if I am incorrect
Python 3.6
*很确定 .extend() 适用于任何可迭代对象,但如果我不正确,请发表评论
回答by dalonsoa
Actually, there are differences among the three options: ADD, INPLACE_ADDand extend. The former is always slower, while the other two are roughly the same.
实际上,三个选项之间存在差异:ADD,INPLACE_ADD和extend。前者总是较慢,而其他两个大致相同。
With this information, I would rather use extend, which is faster than ADD, and seems to me more explicit of what you are doing than INPLACE_ADD.
有了这些信息,我宁愿使用extend,它比 快ADD,而且在我看来比INPLACE_ADD.
Try the following code a few times (for Python 3):
尝试几次以下代码(对于 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
回答by Flux
I've looked up the official Python tutorial but couldn't find anything anything about this topic
我查了官方的 Python 教程,但找不到关于这个话题的任何信息
This information happens to be buried in the Programming FAQ:
此信息恰好隐藏在编程常见问题解答中:
... for lists,
__iadd__[i.e.+=] is equivalent to callingextendon the list and returning the list. That's why we say that for lists,+=is a "shorthand" forlist.extend
... 对于列表,
__iadd__[ie+=] 相当于调用extend列表并返回列表。这就是为什么我们说对于列表来说,+=是一个“简写”list.extend
You can also see this for yourself in the CPython source code: https://github.com/python/cpython/blob/v3.8.2/Objects/listobject.c#L1000-L1011
您也可以在 CPython 源代码中亲自查看:https: //github.com/python/cpython/blob/v3.8.2/Objects/listobject.c#L1000-L1011


