如何包装或嵌入发电机?

银河系

我正在尝试提供一个统一的接口,用于从单个目录或目录列表中检索所有文件。

def get_files(dir_or_dirs):
    def helper(indir):
        file_list = glob.glob("*.txt")
        for file in file_list:
            yield file

    if type(dir_or_dirs) is list:
        # a list of source dirs
        for dir in dir_or_dirs:
            yield helper(dir)
    else:
        # a single source dir
        yield helper(dir_or_dirs)

def print_all_files(file_iter):
    for file in file_iter:
        print(file)        # error here!

问题:

  1. 该错误表明“文件”仍然是生成器,而不管输入是单个目录还是目录。为什么它仍然是发电机?
  2. 是否可以将生成器包装或嵌入到函数中?如果是这样,如何进行这项工作?
马丁·彼得斯(Martijn Pieters)

helper()每次都屈服

yield helper(dir)

helper()它本身就是一个发电机。

在Python 3.3及更高版本中,请yield from改用:

yield from helper(dir)

控制权委派给另一个生成器。Yield表达式文档中:

yield from <expr>被使用时,它把所提供的表达式作为subiterator。该子迭代器产生的所有值都直接传递给当前生成器方法的调用者。

在较旧的Python版本(包括Python 2.x)中,请使用另一个循环:

for file in helper(dir):
    yield file

有关操作的更多信息yield from,请参见PEP 380-委托给子生成器的语法

并不是说您真的需要帮助器功能,它不只是循环glob.glob()结果,还可以直接执行它

您还需要更正实际使用的功能indir当前,您正在忽略该参数,因此只能从当前工作目录中获取文本文件

接下来,您要使用glob.iglob()而不是进行glob.glob()延迟评估,os.scandir()而不是一次将所有结果加载到内存中。我只是将一个非列表dir_or_dirs值变成一个列表,然后使用一个循环:

import glob
import os.path

def get_files(dirs):
    if not isinstance(dirs, list):
        # make it a list with one element
        dirs = [dirs]

    for dir in dirs:
        pattern = os.path.join(dir, '*.txt')
        yield from glob.iglob(pattern)

现在,我将使用可变数量的参数,而不是字符串或列表的单个参数,并使用*args参数语法:

def get_files(*dirs):
    for dir in dirs:
        pattern = os.path.join(dir, '*.txt')
        yield from glob.iglob(pattern)

可以使用0个或更多目录来调用:

for file in get_files('/path/to/foo', '/path/to/bar'):
    # ...

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章