Замена генератора другой функцией - Python 3.x - PullRequest
0 голосов
/ 20 февраля 2019

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

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

change_generator не дает желаемого результата. Я могу изменить только change_generator.

Я не могу изменить positive_integers_generator() и цикл for ниже.

Могу ли я решить эту проблему с помощью декоратора?

#can't change the body of this function
def positive_integers_generator():
    n = 1
    while True:
        x = yield n
        if x is not None:
            n = x
        else:
            n += 1

# can only change this function            
def change_generator(generator, n):
  for i in generator:
    if i%2 == 0:
      yield(i)



# can't change this code either
# should print 1, 2, 4, 6, 8
g = positive_integers_generator() 
for _ in range(5):
    n = next(g)
    print(n)
    change_generator(g, n)

Ответы [ 3 ]

0 голосов
/ 21 февраля 2019

Вы можете использовать встроенную функцию filter

even_numbers_generator = filter(lambda n: n % 2 == 0, positive_integers_generator())

Или выражение генератора.

even_numbers_generator = (n for n in positive_integers_generator() if n % 2 == 0)

Или itertools.count из стандартной библиотеки:

even_numbers_generator = itertools.count(start=2, step=2)

Но если вы можете изменить только функцию change_generator, для «правильного ответа» на вызов, вероятно, потребуется использовать generator.send ()

# can only change this function            
def change_generator(generator, n):
    if n % 2 == 0:
        generator.send(n + 1)
0 голосов
/ 21 февраля 2019

В вашей очень специфической проблеме, если вы не можете изменить часть print(n), тогда вы загнаны в угол, потому что вы не можете изменить экземпляр генератора g, который был создан для positive_integers_generator().

В том, что может быть неодобрительным ответом, в данном конкретном случае вы можете обновить global g, чтобы переназначить его на новый generator после этого:

def change_generator(generator, n):
    def even_gen():
        n = 2
        while True:
            if n % 2 == 0:
                yield n
            else:
                yield
            n += 1
    global g                          # directly change the g referenced in main code
    if not g.__name__ == 'even_gen':  # change g if it is not even_gen
        g = even_gen()

# output:
# 1
# 2
# None
# 4
# None
0 голосов
/ 20 февраля 2019

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

def positive_integers_generator():
    n = 1
    while True:
        x = yield n
        if x is not None:
            n = x
        else:
            n += 1

def change_generator(generator):
  for i in generator:
    if i%2 == 0:
      yield i

g = positive_integers_generator()

# should print 1, 2, 4
for _ in range(5):
  n = next(change_generator(g))
  print(n)
...