函数生成器与Python 3中的类生成器

时间:2016-08-10 11:25:56

标签: python python-3.x generator

为什么函数生成器和类生成器的行为不同?我的意思是,使用类生成器我可以根据需要多次使用生成器,但是使用函数生成器,我只能使用它一次?为什么这样?

def f_counter(low,high):
    counter=low
    while counter<=high:
        yield counter
        counter+=1

class CCounter(object):
    def __init__(self, low, high):
        self.low = low
        self.high = high
    def __iter__(self):
       counter = self.low
       while self.high >= counter:
            yield counter
            counter += 1

f_gen=f_counter(5,10)
for i in f_gen:
    print(i,end=' ')

print('\n')

for j in f_gen:
    print(j,end=' ')  #no output

print('\n')

c_gen=CCounter(5,10)
for i in c_gen:
    print(i,end=' ') 

print('\n')

for j in c_gen:
    print(j,end=' ')

2 个答案:

答案 0 :(得分:5)

调用f_gen()函数会产生iterator(具体而言,是generator iterator)。迭代器只能循环一次。你的类是不是一个迭代器,而是一个iterable,一个可以生成任意数量的迭代器的对象。

每次使用for时,您的类都会生成一个 new 生成器迭代器,因为for会在您传入的对象上应用iter() function调用object.__iter__(),在您的实现中,每次调用它时都会返回 new 生成器迭代器。

换句话说,您可以在循环之前调用iter(instance)instance.__iter__()来使该行的行为相同:

c_gen = CCounter(5,10)
c_gen_iterator = iter(c_gen)
for i in c_gen_iterator:
    # ...

您还可以从CCounter()返回self并添加object.__next__() method__iter__,将object.next()转换为迭代器在Python 2):

class CCounter(object):
    def __init__(self, low, high):
        self.low = low
        self.high = high
    def __iter__(self):
       return self
    def __next__(self):
       result = self.low
       if result >= self.high:
           raise StopIteration()
       self.low += 1
       return result

答案 1 :(得分:2)

您的类是可迭代的,但不是迭代器本身。每次在其上调用iter时,都会得到一个新的迭代器。

如果你想用类复制生成器函数的行为,那么你想要一个像这样的迭代器:

class CCounter(object):
    def __init__(self, low, high):
        self.low = low
        self.high = high
        self.counter = self.low
    def __iter__(self):
       return self
    def __next__(self):
       if self.counter > self.high:
           raise StopIteration()
       val = self.counter
       self.counter += 1
       return val