32

ジェネレーター スタイルは、リストを返すよりも直接的である可能性があると何度も考えてきました。たとえば、

def foo(input_array):
    for x in input_array:
        yield processed(x)

対。

def bar(input_array):
    accumulator = []
    for x in input_array:
        accumulator.append(processed(x))
    return accumulator

(わかりました、それが本当に簡単なら、私は書きmapますが、要点はわかります:ジェネレーターのバージョンはよりクリーンです)。ただし、ジェネレーターの戻り値の型が常に必要なわけではありません。fooリストまたはタプルを返す関数に変更するために使用できる組み込みのデコレータはありますか? 自分で書くとこうなりますが、

import functools

def transform_return_value(transformer):
    def inner(f):
        @functools.wraps(f)
        def new_f(*argv, **kwargs):
            return transformer(f(*argv, **kwargs))
        return new_f
    return inner

@transform_return_value(list)
def foo(input_array):
    for x in input_array:
        yield processed(x)
4

4 に答える 4

27

私の知る限りでは(まったく同じことを考えていたので調べました)、いいえ:標準ライブラリでこれを行う直接的な方法はありません。

listifyただし、unstdlib.py ライブラリには完全にテストされたラッパーがあります: https://github.com/shazow/unstdlib.py/blob/master/unstdlib/standard/list_.py#L149

def listify(fn=None, wrapper=list):
    """
    A decorator which wraps a function's return value in ``list(...)``.

    Useful when an algorithm can be expressed more cleanly as a generator but
    the function should return an list.

    Example::

        >>> @listify
        ... def get_lengths(iterable):
        ...     for i in iterable:
        ...         yield len(i)
        >>> get_lengths(["spam", "eggs"])
        [4, 4]
        >>>
        >>> @listify(wrapper=tuple)
        ... def get_lengths_tuple(iterable):
        ...     for i in iterable:
        ...         yield len(i)
        >>> get_lengths_tuple(["foo", "bar"])
        (3, 3)
    """
    def listify_return(fn):
        @wraps(fn)
        def listify_helper(*args, **kw):
            return wrapper(fn(*args, **kw))
        return listify_helper
    if fn is None:
        return listify_return
    return listify_return(fn)
于 2012-09-11T20:03:26.977 に答える
7

Although @David Wolever's answer is suerly the cleanest way, one thing I often find myself doing (as it doesn't require to define an external decorator) is writing the generator as a local function, like this:

def foo(input_array):
    def gen():
        for x in input_array:
            yield processed(x)

    return list(gen())
于 2015-04-27T08:40:31.243 に答える
-5

効率的で簡潔なリスト定義を行うには、リスト内包表記を使用してみてください。

def foo(input_array):
    return [processed(x) for x in input_array]

関数がリストを返すようにしたい場合は、リストを返すようにします。これは、decorator を使用するよりもはるかにクリーンで、理解しやすく、読みやすく、デバッグしやすいです。

関数を呼び出すよりも、インラインで記述した方がよい場合があります。

于 2012-09-11T20:14:11.507 に答える