Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a library function in Python to turn a generator-function into a function returning a list?

A number of times I've thought that generator style can be more direct that returning a list, for example,

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

vs.

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

(okay, if it were really that simple, I'd write map, but you get the point: the generator version is cleaner). However, a return type of a generator is not always desired. Is there a built-in decorator that I can use to change foo into a function returning a list or tuple? The way I'd write it myself is,

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) 
like image 763
gatoatigrado Avatar asked Sep 11 '12 19:09

gatoatigrado


People also ask

Can generator function have return in Python?

It uses yield instead of return keyword. So, this will return the value against the yield keyword each time it is called. However, you need to create an iterator for this function, as shown below. The generator function cannot include the return keyword.

How do you yield a generator in Python?

You can assign this generator to a variable in order to use it. When you call special methods on the generator, such as next() , the code within the function is executed up to yield . When the Python yield statement is hit, the program suspends function execution and returns the yielded value to the caller.

Does generator function has a return statement?

A return statement in a generator, when executed, will make the generator finish (i.e. the done property of the object returned by it will be set to true ). If a value is returned, it will be set as the value property of the object returned by the generator.


1 Answers

To the best of my knowledge (and I've looked, because I've wondered exactly the same thing), no: there is no direct way of doing this with the standard library.

There is a thoroughly tested listify wrapper in unstdlib.py library, though: 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) 
like image 161
David Wolever Avatar answered Sep 17 '22 13:09

David Wolever