2

通常,当我使用 Python 时,我会发现自己编写的列表推导式看起来像这样:

num_foobars = 10
foobars = [create_foobar() for idx in xrange(num_foobars)]

显然,这很好用,但是当我根本没有真正使用该信息时,创建一个范围并在其中迭代虚拟索引对我来说仍然有点尴尬。

我一点也不关心性能或类似的东西,只是感觉它不像 Python 通常那样优雅。

我想知道是否有任何很好的惯用方式来避免不必要的列表理解语法,也许使用类似map或 in 的东西itertools,给我看起来更像......

num_foobars = 10
foobars = repeat(create_foobar, num_foobars)
4

4 回答 4

6

这是itertools的方式:

list(starmap(create_foobar, repeat((), 10)))

itertools 方式短而快。也就是说,我更喜欢列表理解:-)

于 2012-01-18T14:27:15.787 回答
1

create_foobar接受参数的情况下,只需遍历参数列表即可。如在

[create_foobar(x) for x in arg_list]

或者

[create_foobar(*x) for x in [arg_tuple] * 10]

但在create_foobar不带参数的特殊情况下,我想你可以这样做:

>>> class Foobar(object):
...     def __init__(self):
...         self.a = random.randrange(0, 10)
...     def __repr__(self):
...         return str(self.a)
... 
>>> map(lambda x: x(), [Foobar] * 10)
[2, 5, 3, 4, 7, 4, 6, 3, 3, 6]

不过 lambda 有点难看。呼应Raymond Hettinger的观点,我认为标准列表理解更可取。还值得注意的是,这会创建一个相当长且无用的列表进行迭代,而标准方法会避免这种情况。您可以通过使用itertools.repeat创建一个可迭代的Foobars... 来解决这个问题,这会增加更多的复杂性。

>>> map(lambda x: x(), itertools.repeat(Foobar, 10))
[1, 4, 4, 6, 2, 4, 9, 9, 1, 6]

更一般地,考虑一下:如果你不迭代任何东西,那么必须有一个索引变量,即使它是隐藏的;并且显式优于隐式。

于 2012-01-18T14:38:46.610 回答
0

您可以定义函数repeat,但编写它的惯用方式仍然是

def repeat(f, max_n):
    return [f(i) for i in xrange(max_n)]

对于那个很抱歉。我同意xrange基于 - 的结构通常看起来很难看,但这正是语言的工作方式。

于 2012-01-18T14:21:28.537 回答
-1
def repeat(creator, num):
    return [create() for x in xrange(num)]

;C)

于 2012-01-18T14:21:49.797 回答