消费者Python生成器的不同行为取决于实现

时间:2017-09-28 08:13:00

标签: python python-2.7 python-3.x generator

考虑以下代码示例。我定义了两个生成器的实现,它产生数字0,1,2。我的期望是SimpleClass()。classgen的行为与mygen相同。我知道发电机只能消耗一次。这意味着只能迭代一次生成器。

class SimpleClass(object):
    @property
    def classgen(self):
        for i in range(3):
            yield i

mygen = (p for p in range(3))


##### Test behavior
sc = SimpleClass()
print(type(sc.classgen))
print(type(mygen))
print("")

print("Iterating over new sc.classgen")
for i in sc.classgen:
    print(i)
print("")

print("Iterating over consumed sc.classgen")
for i in sc.classgen:
    print(i)
print("")


print("Iterating over new mygen")
for i in mygen:
    print(i)
print("")

print("Iterating over consumed mygen")
for i in mygen:
    print(i)

我的期望是每个发生器的第一次迭代打印数字0,1,2,实际上就是正在发生的事情。但是我希望当我第二次在每个发生器上进行迭代时,我会看到没有打印。对mygen的第二个循环来说也是如此,但sc.classgen上的第二个循环仍会打印数字0,1,2。我无法解释为什么会这样。我以为发电机只能使用一次?

2 个答案:

答案 0 :(得分:1)

这是因为你没有调用同一个生成器,如果你将sc.classgen赋给变量,它的行为就像你期望的那样。

class SimpleClass(object):
    @property
    def classgen(self):
        for i in range(3):
            yield i

mygen = (p for p in range(3))


##### Test behavior
sc = SimpleClass()
print(type(sc.classgen))
print(type(mygen))
print("")

g = sc.classgen

print("Iterating over new sc.classgen")
for i in g:
    print(i)
print("")

print("Iterating over consumed sc.classgen")
for i in g:
    print(i)
print("")


print("Iterating over new mygen")
for i in mygen:
    print(i)
print("")

print("Iterating over consumed mygen")
for i in mygen:
    print(i)

由于classgen属性是一个函数,每次访问它时都会创建一个新函数。

答案 1 :(得分:1)

@property不会缓存方法的返回值,因此每次调用sc.classgen时都会使用不同的生成器。你可以测试一下:

import time


class SimpleClass(object):
    @property
    def the_time(self):
        return time.time()


sc = SimpleClass()

time1 = sc.the_time
time.sleep(2)
time2 = sc.the_time

print(time1 == time2)
> False