0

我有一个根据标志返回生成器或列表的函数。

然而,即使我为list函数设置了标志,它仍然返回一个生成器;也不打印标志。

我希望先评估 yield 命令之前的打印语句。同样,如果标志设置为,list我不希望该generator块进行评估。

import os

def get_iterator_all_files_name(dir_path, flag):
    if flag == 'generator':
        print(flag)
        for (dirpath, dirnames, filenames) in os.walk(dir_path):
            for f in filenames:
                yield os.path.join(dirpath, f)
    elif flag == 'list':
        print(flag)
        paths = list()
        for (dirpath, dirnames, filenames) in os.walk(dir_path):
            for f in filenames:
                paths.append(os.path.join(dirpath, f))
        return paths

使用功能...

file_path = 'path/to/files'
flag = 'list'
foo = get_iterator_all_files_name(file_path, flag)
type(foo)

这会产生结果......

generator

这不是我所期望的;我期待着名单。

4

2 回答 2

1

任何具有yield语句的函数都成为生成器函数,因此,它的return语句具有不同的含义(与return普通函数的语句相比)。如果您确实需要该get_iterator_all_files_name函数有时返回生成器而有时返回列表,则一种方法是:

  1. 在子句中再定义一个函数(比如my_gen_func)来执行您现在正在执行的操作。if因此,这个新函数将是一个生成器函数(因为它有一个yield语句)。
  2. get_iterator_all_files_name函数内部,修改if子句,只调用my_gen_func,并返回它的返回值。(现在,您的get_iterator_all_files_name函数不再是生成器函数,而只是一个普通函数,因为它没有yield语句)
  3. 您的elif条款可以保持不变。
于 2019-02-05T05:31:23.197 回答
1

如果一个函数中有这个词yield,它就是一个生成器。没有例外。在尝试迭代之前不会评估代码。

只需调用list结果即可:

def get_iterator_all_files_name(dir_path):
    for (dirpath, dirnames, filenames) in os.walk(dir_path):
        for f in filenames:
            yield os.path.join(dirpath, f)

file_path = 'path/to/files'
foo = list(get_iterator_all_files_name(file_path))

如果您真的想保留该flag功能,您可以修改您的函数以返回生成器。你也可以做paths一个列表推导,这样可以简化功能:

def get_iterator_all_files_name(dir_path, flag):
    if flag == 'generator':
        return (os.path.join(dirpath, f) for (dirpath, dirnames, filenames) in os.walk(dir_path) for f in filenames)
    elif flag == 'list':
        return [os.path.join(dirpath, f) for (dirpath, dirnames, filenames) in os.walk(dir_path) for f in filenames]
于 2019-02-05T05:13:31.260 回答