gpt4 book ai didi

Python 列表理解仅适用于特定顺序

转载 作者:太空宇宙 更新时间:2023-11-03 14:27:55 25 4
gpt4 key购买 nike

我有一个小代码行(loc)计数器;这很简单,所以我想我应该尝试一下作为一个漂亮的列表理解。

但是,在执行代码时;发生了一些奇怪的事情:当我像这样执行代码时

from os import listdir, path

PYTHON_FILES = [
filename for filename in listdir(path.dirname(__file__))
if filename.endswith('.py')
]

def count_lines(list_of_files):
"""Count sloc in iterable list_of_files"""

loc = 0

# Redundant, but code only works
# when this part is in
# Even though what it does gets overwritten
for file in list_of_files:
for line in open(file):
if not line.strip().startswith('#'):
if not line.strip().startswith('"'):
if not line.isspace():
loc += 1

loc = len([
line for line in open(file)
for file in list_of_files
if not line.strip().startswith('#')
and not line.strip().startswith('"')
and not line.isspace()
])

print(loc)

count_lines(PYTHON_FILES)

它运行顺利并且输出符合预期。但是当我用这个替换 count_lines 时:

def count_lines(list_of_files):
"""Count sloc in iterable list_of_files"""

loc = len([
line for line in open(file)
for file in list_of_files
if not line.strip().startswith('#')
and not line.strip().startswith('"')
and not line.isspace()
])

print(loc)

我明白了:

  File "counter.py", line 22, in count_lines
line for line in open(file)
NameError: name 'file' is not defined

我不确定为什么会发生这种情况:for 循环中的file 应该是该迭代的本地文件。那么为什么它会影响其他一切呢?

最佳答案

列表理解

这是预期的行为。列表理解在右侧有一系列循环( for <var> in <iterable> )和过滤器( if <expr> )。它只能使用在列表理解之外定义的变量,或者在上一个循环中定义的变量。

所以你不能写for x in y for y in z ,自 y尚未在第一个序列中定义。您需要自己执行分层,以便您使用的变量在循环语句之前定义。

这是合乎逻辑的,因为如果你写:

[
line for line in open(file)
for file in list_of_files
if not line.strip().startswith('#')
and not line.strip().startswith('"')
and not line.isspace()
]

它相当于下面的过程代码:

<b>result = []</b>
for line in open(<b>file</b>):
for <b>file</b> in list_of_files:
if not line.strip().startswith('#') and not line.strip().startswith('"') and not line.isspace():
<b>result.append(line)</b>

因此,这里您将有一个外部循环,它迭代内部循环中分配的变量。这是没有意义的。虽然肯定有一种方法可以自动进行排序(分层),但自己进行排序具有优势,因为内/外循环的顺序也决定了结果的顺序。

“泄漏变量”

为什么你的第一种方法没有出现错误?自从您第一次使用 for循环,变量泄漏。事实上,如果我们写:

>>> for x in [1,4,2,5]:
... pass
...
>>> x
5

我们看到for之后循环,变量 x仍然存在,并且具有最后分配的值。因此,如果您稍后编写列表理解,它将首先评估第一个 for列表理解中的循环,即 for line in open(file)file仍然被分配,因此最后一个文件被打开并处理。

请注意line只会从最后一个文件中获取行,并且我们将多次处理最后一个文件中的每一行(对于每个 file in files )。但我们不会处理最后一个文件以外的其他文件(但数字将乘以文件数)。

关于Python 列表理解仅适用于特定顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47497321/

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