用于在列表中创建给定数量元素的Python习惯用法

时间:2012-01-18 14:18:58

标签: python

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

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

显然这样可以正常工作,但是当我实际上根本没有使用该信息时,我仍然觉得创建一个范围并在其上迭代虚拟索引有点尴尬。

我并不以任何方式关注性能或类似的东西,它只是感觉不像Python通常那么优雅。

我想知道是否有任何不错的惯用方法来避免列表理解语法的不必要的部分,可能使用mapitertools中的某些东西来给我看起来更像的代码。 ..

num_foobars = 10
foobars = repeat(create_foobar, num_foobars)

4 个答案:

答案 0 :(得分:6)

这是itertools方式:

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

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

答案 1 :(得分: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创建一个Foobar的迭代来解决这个问题...添加更多的复杂功能。

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

更一般地说,考虑一下:如果你没有在任何事情上迭代,就必须有一个索引变量,即使它被隐藏了;而显式优于隐式。

答案 2 :(得分:0)

你可以定义函数repeat,但是写它的惯用方法仍然是

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

很抱歉。我同意基于xrange的构造通常看起来很难看,但它只是语言的工作方式。

答案 3 :(得分:-1)

def repeat(creator, num):
    return [create() for x in xrange(num)]

; c)中