简体   繁体   English

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

[英]list() vs iterable unpacking in Python 3.5+

在支持后者的 Python 版本中, list(iterable)[*iterable]之间有什么实际区别吗?

list(x) is a function, [*x] is an expression. list(x)是一个函数, [*x]是一个表达式。 You can reassign list , and make it do something else (but you shouldn't).您可以重新分配list ,并使其执行其他操作(但您不应该这样做)。

Talking about cPython, b = list(a) translates to this sequence of bytecodes:谈到 cPython, b = list(a)转换为以下字节码序列:

LOAD_NAME                1 (list)
LOAD_NAME                0 (a)
CALL_FUNCTION            1
STORE_NAME               2 (b)

Instead, c = [*a] becomes:相反, c = [*a]变为:

LOAD_NAME                0 (a)
BUILD_LIST_UNPACK        1
STORE_NAME               3 (c)

so you can argue that [*a] might be slightly more efficient, but marginally so.所以你可以争辩说[*a]可能稍微更有效率,但稍微有效一点。

You can use the standard library module dis to investigate the byte code generated by a function.您可以使用标准库模块dis来调查函数生成的字节码。 In this case:在这种情况下:

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

So there is a difference and it is not only the loading of the globally defined name list , which does not need to happen with the unpacking.所以有区别,不仅仅是全局定义的名称list的加载,这不需要在解包时发生。 So it boils down to how the built-in list function is defined and what exactly BUILD_LIST_UNPACK does.所以它归结为内置list函数的定义方式以及BUILD_LIST_UNPACK作用。

Note that both are actually a lot less code than writing a standard list comprehension for this:请注意,与为此编写标准列表推导式相比,两者实际上都少了很多代码:

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

Since [*iterable] is unpacking, it accepts assignment-like syntax, unlike list(iterable) :由于[*iterable]是解包的,它接受类似赋值的语法,与list(iterable)

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

You can read more about this here (not useful though).您可以在此处阅读有关此内容的更多信息(尽管没有用)。

You can also use list(sequence=iterable) , ie with a key-word argument:您还可以使用list(sequence=iterable) ,即带有关键字参数:

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

Again not useful .又没

There's always going to be some differences between two constructs that do the same thing.做同样事情的两个结构之间总会有一些差异。 Thing is, I wouldn't say the differences in this case are actually practical .问题是,我不会说这种情况下的差异实际上是实用的 Both are expressions that take the iterable, iterate through it and then create a list out of it.两者都是获取可迭代对象的表达式,遍历它然后从中创建一个列表。

The contract is the same: input is an iterable output is a list populated by the iterables elements.契约是相同的:输入是一个可迭代的输出是一个由可迭代元素填充的列表。

Yes, list can be rebound to a different name;是的, list可以反弹到不同的名称; list(it) is a function call while [*it] is a list display; list(it)是一个函数调用,而[*it]是一个列表显示; [*it] is faster with smaller iterables but generally performs the same with larger ones. [*it]使用较小的可迭代对象更快,但通常使用较大的可迭代对象执行相同的操作。 Heck, one could even throw in the fact that [*it] is three less keystrokes.哎呀,甚至可以抛出这样一个事实,即[*it]少了三个击键。

Are these practical though?不过这些实用吗? Would I think of them when trying to get a list out of an iterable?在尝试从可迭代对象中获取列表时,我会想到它们吗? Well, maybe the keystrokes in order to stay under 79 characters and get the linter to shut it up.好吧,也许是为了保持在 79 个字符以下并让 linter 关闭它的击键。

显然,在 CPython 中存在性能差异,其中[*a]过度分配而list()不会: 是什么导致 [*a] 过度分配?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM