Заполните список или кортеж из вызываемого или лямбда-кода в Python - PullRequest
4 голосов
/ 02 января 2012

Это проблема, с которой я часто сталкивался в последнее время. У Google, похоже, нет ответа, поэтому я довожу его до сведения людей о переполнении стека.

Я ищу простой способ заполнить список выводом функции. Примерно так:

fill(random.random(), 3) #=> [0.04095623, 0.39761869, 0.46227642]

Вот другие способы, которые я нашел для этого. Но я не очень доволен ими, потому что они кажутся неэффективными.

results = []
for x in xrange(3): results.append(random.random())
#results => [0.04095623, 0.39761869, 0.46227642]

и

map(lambda x: random.random(), [None] * 3)
#=> [0.04095623, 0.39761869, 0.46227642]

Предложения


Спасибо за все ответы. Я знал, что есть более питонский способ.

А к вопросам эффективности ...

$ python --version
Python 2.7.1+
$ python -m timeit "import random" "map(lambda x: random.random(), [None] * 3)"
1000000 loops, best of 3: 1.65 usec per loop
$ python -m timeit "import random" "results = []" "for x in xrange(3): results.append(random.random())"
1000000 loops, best of 3: 1.41 usec per loop
$ python -m timeit "import random" "[random.random() for x in xrange(3)]"
1000000 loops, best of 3: 1.09 usec per loop

Ответы [ 5 ]

11 голосов
/ 02 января 2012

Как насчет понимания списка ?

[random.random() for x in xrange(3)]

Кроме того, во многих случаях вам нужны значения только один раз.В этих случаях предпочтительным является генераторное выражение , которое вычисляет значения точно в срок и не требует выделения памяти:

results = (random.random() for x in xrange(3))
for r in results:
   ...
# results is "used up" now.
# We could have used results_list = list(results) to convert the generator

Кстати, в Python 3.x, xrange был заменен на range.В Python 2.x range выделяет память и заранее вычисляет все значения (как в случае со списком), тогда как xrange вычисляет значения точно в срок и не выделяет память (это генератор).

2 голосов
/ 02 января 2012

почему вы думаете, что они неэффективны?

Есть еще один способ сделать это, понимание списка

listt= [random.random() for i in range(3)]
0 голосов
/ 02 января 2012

Понимание списка, вероятно, яснее, но для itertools afficionado:

>>> list(itertools.islice(iter(random.random, None), 3))
[0.42565379345946064, 0.41754360645917354, 0.797286438646947]

Быстрая проверка с помощью timeit показывает, что версия itertools немного быстрее для более чем 10 элементов, но все же идет с тем, что кажется вам более понятным:

C:\Python32>python lib\timeit.py -s "import random, itertools" "list(itertools.islice(iter(random.random, None), 10))"
100000 loops, best of 3: 2.93 usec per loop

C:\Python32>python lib\timeit.py -s "import random, itertools" "[random.random() for _ in range(10)]"
100000 loops, best of 3: 3.19 usec per loop
0 голосов
/ 02 января 2012

нечто более общее ...

from random import random

fill = lambda func, num: [func() for x in xrange(num)]
# for generating tuples:
fill = lambda func, num: (func() for x in xrange(num))


# then just call:
fill(random, 4)
# or...
fill(lambda : 1+2*random(), 4)
0 голосов
/ 02 января 2012
   list =  [random.random() for i in xrange(3)]
   list =  [random.random() for i in [0]*3]
   list =  [i() for i in [random.random]*3]

Или:

  fill =lambda f,n: [f() for i in xrange(n)]
  fill(random.random , 3 ) #=> [0.04095623, 0.39761869, 0.46227642]
...