повторно использовать генераторы - PullRequest
2 голосов
/ 18 апреля 2010

Я хочу проверить центральный лимит с кубиками. Ролл D кубики. Подведите итоги. Повторите то же самое для N раз. Измените D и повторите.

Нет необходимости хранить случайные значения, поэтому я хочу использовать только генераторы. Проблема в том, что генераторы потребляются; Я не могу использовать их много раз. Теперь мой код использует явное for, и мне оно не нравится.

dice_numbers = (1, 2, 10, 100, 1000)
repetitions = 10000
for dice_number in dice_numbers: # how many dice to sum
    sum_container = []
    for r in range(repetitions):
        rool_sum = sum((random.randint(1,6) for _ in range(dice_number)))
        sum_container.append(rool_sum)
        plot_histogram(sum_container)

Я хочу создать что-то вроде

for r in repetitions:
    rools_generator = (random.randint(1,6) for _ in range(dice_number)
    sum_generator = (sum(rools_generator) for _ in range(r))

но второй раз, когда я повторно использую rools_generator, он потребляется. Нужно ли создавать класс генератора?

Ответы [ 3 ]

5 голосов
/ 18 апреля 2010

Вы можете сделать это так:

for r in repetitions:
    make_rools_generator = lambda: (random.randint(1,6) for _ in range(dice_number))
    sum_generator = (sum(make_rools_generator()) for _ in range(r))

Это создает функцию с именем make_rools_generator, которая при вызове создает новый генератор, который поставляет броски костей.

2 голосов
/ 18 апреля 2010

Я думаю, что вы, возможно, слишком усердно работаете, и вы определенно создаете ненужные списки с помощью range (). В духе того, чтобы быть немного более явным, чем указанное выше выражение genxprs:

import random

def die_roller(throws):
    """generates throws rolls of a die"""
    for _ in xrange(throws):
        yield random.randint(1, 6)

roller = die_roller(10)
print type(roller)      # => <type 'generator'>
print list(roller)      # => [6, 6, 3, 1, 6, 3, 1, 5, 4, 4]
print sum(roller)       # roller was exhausted, generates null list thus 0 sum

big_roller = die_roller(10**5)
print sum(big_roller)   # => 3500238

Я думаю, что это дает вам зачатки того, что вы ищете.

0 голосов
/ 18 апреля 2010

Что по этому поводу:

list(list((sum((random.randint(1,6) for _ in range(dn))) for __ in range(10000))) for dn in (1, 2, 10, 100, 1000))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...