【问题标题】:How could I rewrite this for loop in list comprehensions我如何在列表推导中重写这个 for 循环
【发布时间】:2014-01-19 15:18:32
【问题描述】:

我有一个这样的“for循环”:

for dirctory in dirs:
    for item in os.walk(dirctory):
        for i in item[2]:
            i = os.path.join(item[0], i)
            if is_image(i):
                images.append(i)

我尝试将其重写为列表推导,我尝试了这个:

images.extend(filter(is_image, [item[0]+i for i in item[2] for item in os.walk(dirctory)]))

它说 UnboundLocalError: local variable 'item' referenced before assignment

所以我尝试了这个:

images.extend(filter(is_image, [(item[0]+i for i in item[2]) for item in os.walk(dirctory)]))

它说 TypeError: coercing to Unicode: need string or buffer, generator found

我在 OS X 中使用 Python 2.7.4。

【问题讨论】:

  • 不是python专家,但是上面代码对应的列表推导可能有点长而且难以阅读。它也有副作用,我认为你通常会避免在列表理解中这样做。 edit 啊 nvm,我看到你只打算对部分代码使用列表理解。哎呀。我会说它仍然有点长
  • 为了清晰和可读性,我个人会将其保留为嵌套循环。
  • 问问你自己为什么要将它作为列表理解?在我看来,如果很难阅读和理解列表理解不是你想要的。只是认为其他人需要理解这个列表理解......
  • 代码中的一个缺陷 - 将所有组件作为单个项目降低了可读性。在类似情况下,变量的显式命名比晦涩的索引更好。
  • all_directories = chain(*map(os.walk, dirs)) full_filenames = lambda root, dirs, files: map(lambda file: os.path.join(root, file), files) image_files = filter(is_image, starmap(full_filenames, all_directories)

标签: python python-2.7 for-loop list-comprehension


【解决方案1】:

试试这个:

[os.path.join(item[0], i) for directory in dirs for item in os.walk(dirctory) for i in item[2] if is_image(os.path.join(item[0], i))]

【讨论】:

  • 使用filter(),我只能使用一次os.path.join,这样会更好吗?像这样: images.extend(filter(is_image, [os.path.join(p, f) for p, _, files in os.walk(dirctory) for f in files]))
【解决方案2】:
def check_image(directory, file_name):
    file_name = os.path.join(directory, file_name)
    return is_image(file_name), file_name

[full_path
     for current_dir in dirs
     for parent_dir, _, files in os.walk(current_dir)
     for current_file in files
     for isimage, full_path in [check_image(parent_dir, current_file)]
         if isimage]

check_image 函数用于避免两次应用os.path.join

【讨论】:

    【解决方案3】:

    这是如何完成的(这与我测试的不完全一样)

    [os.path.join(path+fname)  for path, _, files in os.walk('some_folder') 
     for fname in files if os.image(os.path.join([path,fname]))]
    

    但是 - 如果你注意 - 在这个解决方案中你必须加入两次路径,所以直接嵌套循环可能更有效

    编辑:

    在我的示例中,我通过扩展名查找 Python 文件,因此在这种情况下,列表理解不会受到路径/文件名双重连接的影响

    【讨论】:

    • 在不使用 os.walk 的情况下获取所有文件路径的任何其他好主意?顺便说一句,os.image 是错字吗?
    猜你喜欢
    • 2022-01-09
    • 1970-01-01
    • 1970-01-01
    • 2017-04-19
    • 2018-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多