Concatenating two lists - difference between '+=' and extend()
我已经看到在python中有两种(可能更多)连接列表的方法:一种方法是使用extend()方法:
1 2 3 | a = [1, 2] b = [2, 3] b.extend(a) |
另一个使用加号(+)运算符:
1 | b += a |
现在我想知道:这两个选项中的哪一个是"pythonic"的列表连接方式,两者之间有什么区别(我已经查阅了官方的python教程,但找不到关于这个主题的任何内容)。
在字节码级别上唯一的区别是,
这真的没什么好担心的,除非你做了数十亿次这个操作。然而,瓶颈可能在其他地方。
对于非局部变量(非局部变量,也非全局变量)不能使用"+"。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | def main(): l = [1, 2, 3] def foo(): l.extend([4]) def boo(): l += [5] foo() print l boo() # this will fail main() |
这是因为for extend case编译器将使用
您可以链接函数调用,但不能直接+=函数调用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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 |
我会说,当它与numpy(我刚才看到的问题是关于连接两个列表,而不是numpy数组,但因为这可能是一个问题,如我初学者,我希望这可以帮助谁寻求解决这个帖子),为前。
1 2 3 4 | import numpy as np a = np.zeros((4,4,4)) b = [] b += a |
它会错误地返回
值错误:操作数无法与形状(0,)一起广播(4,4,4)
从python 3.5.2源代码:没有什么区别。
1 2 3 4 5 6 7 8 9 10 11 12 | 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; } |
实际上,这三种选择之间存在差异:
有了这些信息,我更愿意使用
尝试以下代码几次(对于Python3):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | 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() |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | 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 |
extend()可以与任何iterable*一起使用,+=可以与某些iterable*一起使用,但会变得很奇怪。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | 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()可以与任何iterable一起使用,但是如果我不正确,请注释。
根据python进行数据分析。
"请注意,通过添加进行列表连接是一个相对昂贵的操作,因为必须创建一个新列表并复制对象。使用extend将元素附加到现有列表中,尤其是在构建大型列表时,通常更可取。"因此,
1 2 3 | everything = [] for chunk in list_of_lists: everything.extend(chunk) |
比连接选项更快:
1 2 3 | everything = [] for chunk in list_of_lists: everything = everything + chunk |