python3中的可选yield或return.如何?

2022-01-19 00:00:00 python python-3.x generator return yield

问题描述

我想要一个可以选择返回或产生结果的函数.这是一个例子.

I would like to have a function that can, optionally, return or yield the result. Here is an example.

def f(option=True):
    ...
    for...:
        if option:
            yield result
        else:
            results.append(result)

    if not option:
        return results

当然,这是行不通的,我用 python3 试过了,不管我设置什么选项值,我总是得到一个生成器.据我了解,python 检查函数的主体,如果存在 yield,则结果将是生成器.有什么办法可以解决这个问题并制作一个可以随意返回或屈服的函数?

Of course, this doesn't work, I have tried with python3 and I always get a generator no matter what option value I set. As far I have understood, python checks the body of the function and if a yield is present, then the result will be a generator. Is there any way to get around this and make a function that can return or yield at will?


解决方案

你不能.任何 yield 的使用都会使函数成为生成器.

You can't. Any use of yield makes the function a generator.

您可以使用一个使用 list() 将生成器生成的所有值存储在列表对象中并返回的函数来包装您的函数:

You could wrap your function with one that uses list() to store all values the generator produces in a list object and returns that:

def f_wrapper(option=True):
    gen = f()
    if option:
        return gen    # return the generator unchanged
    return list(gen)  # return all values of the generator as a list

但是,一般来说,这是糟糕的设计.不要让你的函数像这样改变行为;坚持一种返回类型(生成器或一个对象),不要让它在两者之间切换.

However, generally speaking, this is bad design. Don't have your functions alter behaviour like this; stick to one return type (a generator or an object) and don't have it switch between the two.

考虑将其拆分为两个函数:

Consider splitting this into two functions instead:

def f():
    yield result

def f_as_list():
    return list(f())

如果您需要生成器,请使用 f(),如果您想要列表,请使用 f_as_list().

and use either f() if you need the generator, and f_as_list() if you want to have a list instead.

由于 list() (和 next() 仅访问生成器的一个值)是内置函数,因此您很少需要使用包装器.直接调用这些函数即可:

Since list(), (and next() to access just one value of a generator) are built-in functions, you rarely need to use a wrapper. Just call those functions directly:

# access elements one by one
gen = f()
one_value = next(gen)

# convert the generator to a list
all_values = list(f())

相关文章