我曾多次认为生成器样式可以更直接地返回列表,例如,
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
(好吧,如果真的那么简单,我会写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)
答案 0 :(得分:22)
据我所知(我看过,因为我想知道完全相同的事情),不是:没有直接的方法可以使用标准库。
但是在unstdlib.py库中有一个经过全面测试的listify
包装器: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)
答案 1 :(得分:4)
虽然@David Wolever的回答是最简洁的方式,但我经常发现自己做的一件事(因为它不需要定义外部装饰器)就是将生成器写成本地函数,如下所示:
def foo(input_array):
def gen():
for x in input_array:
yield processed(x)
return list(gen())
答案 2 :(得分:1)
这是一个替代的,简单的装饰者,没有任何铃声和口哨声:
from functools import wraps
from types import GeneratorType
def listify(func):
"""decorator for making generator functions return a list instead"""
@wraps(func)
def new_func(*args, **kwargs):
r = func(*args, **kwargs)
if isinstance(r, GeneratorType):
return list(r)
else:
return r
return new_func
答案 3 :(得分:-3)
要获得高效简洁的列表定义,请尝试使用list comprehension:
def foo(input_array):
return [processed(x) for x in input_array]
如果你想让一个函数返回一个列表,让它返回一个列表。这比使用装饰器更清晰,更容易理解,阅读和调试。
您可能更喜欢内联编写,而不是调用函数。