list()与Python 3.5+中的可迭代解压缩

时间:2018-09-27 14:34:21

标签: python python-3.x list iterable python-internals

在支持list(iterable)[*iterable]的Python版本中,它们之间是否有实际区别?

5 个答案:

答案 0 :(得分:4)

def list_comp(x): return [a for a in x] dis.dis(list_comp) # 2 0 LOAD_CONST 1 (<code object <listcomp> at 0x7f65356198a0, file "<ipython-input-46-dd71fb182ec7>", line 2>) # 2 LOAD_CONST 2 ('list_comp.<locals>.<listcomp>') # 4 MAKE_FUNCTION 0 # 6 LOAD_FAST 0 (x) # 8 GET_ITER # 10 CALL_FUNCTION 1 # 12 RETURN_VALUE 是一个函数,list(x)是一个表达式。您可以重新分配[*x],并使其做其他事情(但不应该这样做)。

谈论cPython,list转换为以下字节码序列:

b = list(a)

相反,LOAD_NAME 1 (list) LOAD_NAME 0 (a) CALL_FUNCTION 1 STORE_NAME 2 (b) 变为:

c = [*a]

因此您可以辩称LOAD_NAME 0 (a) BUILD_LIST_UNPACK 1 STORE_NAME 3 (c) 可能效率更高,但略有提高。

答案 1 :(得分:3)

您可以使用标准库模块dis来调查函数生成的字节码。在这种情况下:

place.getLatLng()

所以有一个区别,不仅是全局定义名称import dis def call_list(x): return list(x) def unpacking(x): return [*x] dis.dis(call_list) # 2 0 LOAD_GLOBAL 0 (list) # 2 LOAD_FAST 0 (x) # 4 CALL_FUNCTION 1 # 6 RETURN_VALUE dis.dis(unpacking) # 2 0 LOAD_FAST 0 (x) # 2 BUILD_LIST_UNPACK 1 # 4 RETURN_VALUE 的加载,而且解压缩时不需要这样做。因此,归结为如何定义内置list函数以及list的作用。

请注意,两者实际上都比编写标准列表理解代码少得多:

BUILD_LIST_UNPACK

答案 2 :(得分:0)

由于[*iterable]正在解压缩,它接受类似于 assignment 的语法,与list(iterable)不同:

>>> [*[]] = []
>>> list([]) = []
  File "<stdin>", line 1
SyntaxError: can't assign to function call

您可以阅读有关此here的更多信息(虽然没有用)。

您还可以使用list(sequence=iterable),即带有关键字参数:

>>> list(sequence=[])
[]

再次not useful

答案 3 :(得分:0)

在做相同事情的两个结构之间总会有一些差异。问题是,我不会说这种情况下的差异实际上是实践。两者都是采用可迭代的表达式,对其进行迭代,然后从中创建一个列表。

合同是相同的:输入是可迭代的输出是由iterables元素填充的列表。

是的,list可以反弹到另一个名称; list(it)是函数调用,而[*it]是列表显示; [*it]使用较小的可迭代项时速度更快,但通常使用较大的迭代器时具有相同的性能。哎呀,甚至可以说[*it]少了三击。

这些实用吗?尝试从迭代列表中获取清单时,我会想到它们吗?好吧,也许击键是为了保持在79个字符以下,并让lint将其关闭。

答案 4 :(得分:0)

显然在CPython中存在性能差异,其中 [* a] 进行整体分配,而 list()则没有:What causes [*a] to overallocate?