简体   繁体   English

使用其他功能更改生成器-Python 3.x

[英]Changing a generator with another function - Python 3.x

I want to change the behavior of the generator below so that it only yields even numbers. 我想在下面更改生成器的行为,使其仅产生偶数。 How can I do this? 我怎样才能做到这一点?

I'm aware that there simpler, clever ways to do this. 我知道有更简单,聪明的方法可以做到这一点。 This is a contrived HR challenge, where the 这是人为的人力资源挑战,

The change_generator function that I wrote does not yield the desired output. 我编写的change_generator函数无法产生所需的输出。 I can only change change_generator . 我只能更改change_generator

I cannot change positive_integers_generator() nor the for loop below. 我无法更改positive_integers_generator()或下面的for循环。

Can I solve this with a decorator? 我可以用装饰器解决吗?

#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)

You can use the built in function filter 您可以使用内置的功能filter

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

Or a generator expression. 或生成器表达式。

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

Or itertools.count from the standard library: 或来自标准库的itertools.count

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

But if you only can change the change_generator function, the "correct answer" to the challenge probably involves using generator.send() 但是,如果您只能更改change_generator函数,则对挑战的“正确答案”可能涉及使用generator.send()

# can only change this function            
def change_generator(generator, n):
    if n % 2 == 0:
        generator.send(n + 1)

You don't need the parens on generator in your loop, and you don't seem to be printing the output of the right generator. 您不需要在循环中的生成器上使用parens,并且您似乎并没有在打印正确的生成器的输出。 Updated version that works for me: 适用于我的更新版本:

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)

In your very specific problem, if you can't change the print(n) part then you are pretty cornered because you can't change the instance of generator g that was created for positive_integers_generator() . 在您的特定问题中,如果您无法更改print(n)部分,那么您将陷入困境,因为您无法更改为positive_integers_generator()创建的生成器g的实例。

In what may be a frowned upon answer, in this particular case you might want to update the global g to be reassigned to a new generator after that: 在这种情况下,您可能会皱着眉头,在这种情况下,您可能想要更新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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM