尝试创建生成器对象但获取不响应生成器调用的函数对象

Trying to create generator object but getting function object that doesn't respond to generator calls

我正在尝试编写一个无限生成器,它将每个正整数重复 n 次。因此,例如,如果我创建 f = inf_repeat(3),打印 f 的输出 10 次将导致:

1 1 1 2 2 2 3 3 3 4

我很接近,但还不够。这是我得到的:

    # courtesy of 
    # a generator that yields items instead of returning a list
    def static_var(varname, value):
        def decorate(func):
            setattr(func, varname, value)
            return func
        return decorate

    def inf_repeat(k):
        count_limit = k
        @static_var("counter", 0)
        @static_var("number", 0)
        def func():
            while True:
                if  func.counter == count_limit:
                    func.counter = 0
                    func.number += 1
                func.counter += 1
                yield func.number
        return func

我的问题是它的行为并不完全像迭代器。以下命令有效:

f3 = inf_repeat(3)
print next(f3())

但是不得不用括号调用 f3 是令人恼火的。我希望能够使用我见过的标准迭代器语法,例如:

print(f3.next())

new_list = [iter(f3)]*5

我需要在我的函数中修改什么才能达到这一点?看了各种生成器教程,好像yield就可以创建一个生成器了,但显然不是这样的。

我也没有 objective 使用模块。我检查了 itertools 但也许我错过了一些无需所有这些代码就可以做我想做的事情?

您只需要在某个时候调用生成器对象(您所谓的 f3)。您可以在创建时调用它:

f3 = inf_repeat(3)()

甚至在 inf_repeat

里面
# change last line to this
return func()

yield 放入您的函数中使其成为一个生成器函数 --- 也就是说,该函数在被调用时 returns 成为一个生成器。如果你想获得生成器,你需要在某个时候调用你的生成器函数。

顺便说一下,您的实现过于复杂了。没有所有这些装饰器和嵌套函数,您可以更简单地获得所需的行为:

def inf_repeat(k):
    number = k
    while True:
        yield number // k
        number += 1

然后:

>>> list(itertools.islice(inf_repeat(3), 10))
[1, 1, 1, 2, 2, 2, 3, 3, 3, 4]
>>> list(itertools.islice(inf_repeat(4), 13))
[1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4]

这是一个简单的解决方案:

def inf_repeat(N):
    i = 1
    while True:
        for n in range(N):
            yield i
        i += 1

# Testing:
f = inf_repeat(3)
for j in range(10):
    print f.next()

这是一个使用 itertools 的解决方案:

def inf_repeat(N):
    return chain.from_iterable(repeat(i, N) for i in count(1))

另一个使用 itertools 的解决方案

import itertools as it

def inf_repeat(k):
    for i in it.count(1):
        for j in [i]*k:
            yield j

for n in inf_repeat(3): print n

生产

1
1
1
2
2
2
...
def f(n):
    i = 0
    while True:
        yield i // n
        i += 1