gpt4 book ai didi

python - Python 中复杂列表理解语句的操作顺序和内部创建资源的数量

转载 作者:行者123 更新时间:2023-11-28 20:33:50 24 4
gpt4 key购买 nike

对于这样的列表理解来说:

foo = [_.strip().split() for _ in foo[10:]]

Python 计算右侧表达式并将其分配给 foo 的确切步骤是什么?在 2.x 和 3.x 之间……处理此类事情的内部逻辑在两者之间有所不同吗?

我想从过程的角度来看,Python 首先执行 foo[10:] 然后开始遍历生成的列表,剥离元素,然后拆分它们,然后将结果附加到一个新列表最后将最后一个列表指向 foo

它是否在内部为每个操作分配一个新列表? (生成的 foo[10:] 的一个列表,然后 strip 的结果的另一个列表,等等?

感谢您的任何见解。

最佳答案

在 Python 3.x 中,您的列表理解被编译成类似这样的东西:

def _comp(it):
result = []
for _ in it:
result.append(_.strip().split())
return result
foo = _comp(iter(foo[10:]))

有一些细微差别——编译器可以使用比 result.append 更快的东西,因为 result 不可访问; _comp 实际上被命名为不是有效标识符的东西,因此您不会不小心调用它;等等。但基本上就是这样。1

有关详细信息,请参阅 Displays for lists, sets, and dictionaries在引用文档中。

那个 foo[10:] 只是调用 foo.__getitem__(slice(None, 10, 10))。如果 foo 是一个 list,则通过创建一个包含从 10 到 foo 末尾的元素的新列表来处理。但是,如果 foo 是一个 numpy 数组,它可能是对 foo 相同内存的 View ,如果它是您刚刚创建的某个疯狂类的实例看看你如何搞砸事情,它可以是你想要的任何东西,比如字符串 'abc'

类似地,如果 foo 的元素是字符串(或 bytes),strip 方法返回一个包含所有字符的新字符串但是复制了剥离的空格,split 方法返回了一个新的复制字符串列表。


在 Python 2.x 中,它更像这样:

_result = []
_it = iter(foo[10:])
for _ in _it:
_result.append(_.strip().split())
foo = _result

尽管再次强调,它不完全是这样——_result_it 的名称不是有效的标识符,append 的优化特殊版本> 被使用,依此类推。

2.x 文档在 List Displays 中.

更改的主要原因是 2.x 设计意味着 _ 泄漏到封闭范围内,2 尽管它允许理解和生成器共享大部分相同代码的表达式是另一个好处。

其他列表和字符串操作在 2.x 和 3.x 之间是相同的。虽然许多函数确实更改为返回迭代器而不是 3.x 中的复制列表,但切片和拆分不在其中。


The tutorial有一个关于理解的很好的部分,但它解释了 2.x 的行为,即使在 3.x 中也是如此(因为它更容易理解,而且差异对新手的代码来说不太重要——毕竟它是一个教程).


<子>1。另外,请注意最外层的可迭代对象作为参数传入的方式。这意味着您不会意外地在闭包中捕获嵌套变量。这对列表理解没有太大影响,但对生成器表达式很重要,在生成器表达式中,迭代可能要等到捕获变量的值发生变化后才会开始。

<子>2。在 2.3-2.6 中,这种泄漏是您可以依赖的官方记录行为。在 2.7 中,它已被弃用,您不应该依赖它泄漏或不泄漏。但是在 2.7 的所有当前主要实现中(并且不会有任何新的实现),列表推导总是会泄漏,尽管集合和字典推导不会。

关于python - Python 中复杂列表理解语句的操作顺序和内部创建资源的数量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49912533/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com