美文网首页
迭代器和生成器

迭代器和生成器

作者: 堪怜咏絮才 | 来源:发表于2020-03-27 10:06 被阅读0次

迭代器

什么是迭代协议?
迭代器是什么?迭代器是访问集合内元素的一种方式,一般用来遍历数据
迭代器和以下标的访问方式不一样。迭代器是不能返回的,迭代器提供了一种惰性方式访问数据

任何实现了iter或者getitem的都是可迭代对象

class Company(object):

    def __init__(self, employee_list):
        self.employees = employee_list

    def __getitem__(self, item):
        return self.employees[item]


company = Company(['张三', '李四', '王五'])
print(isinstance(company, Iterable))
# 执行结果:False
print(isinstance(company, Iterator))
# 执行结果:False
for c in company:
    print(c)
执行结果:
    张三
    李四
    王五

对于for循环来说,首先寻找iter方法,如果没有iter方法,那么就会去寻找getitem方法,这个方法是用来定义序列用的,
如果两个方法都没有,那么就说这个对象是不可迭代的。只要实现了这两个方法中的其中一个,就证明这个对象是可迭代对象。
如果有iter方法,就会得到一个迭代器对象,然后调用迭代器的next方法,获取元素,直到抛出StopIteration异常为止,for循环本身
会对这种异常作出处理。如果有getitem方法,那么就从下标0开始获取数据。
疑问:只有getitem的类的实例是属于可迭代对象,但用isinstances测试collections.Iterable是不能通过的,可以通过iter函数来测试,
如果没报错就说明是可迭代对象,然后生成一个没有next属性的迭代器。

print(dir(company))
'''
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', 
'__getattribute__', '__getitem__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', 
'__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', 
'__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'employees']
'''

迭代器需要实现iternext,iter用来返回一个迭代器,next用来获取下一个元素和抛出StopIteration的异常。
备注:内置函数iter()调用的是iter方法,next()调用的是next方法

class Company(object):

    def __init__(self, employee_list):
        self.employees = employee_list

    def __iter__(self):
        return MyIterator(self.employees)


class MyIterator():

    def __init__(self, iter_list):
        self.iter_list = iter_list
        self.index = 0

    def __iter__(self):
        return self

    def __next__(self):
        try:
            res = self.iter_list[self.index]
        except IndexError:
            raise StopIteration
        self.index += 1
        return res


company = Company(['张三', '李四', '王五'])
print(isinstance(company, Iterable))
# 执行结果:True
print(isinstance(company, Iterator))
# 执行结果:False

my_iterator = MyIterator(['张三', '李四', '王五'])
print(isinstance(my_iterator, Iterable))
# 执行结果:True
print(isinstance(my_iterator, Iterator))
# 执行结果:True
for em in company:
    print(em)
'''
执行结果
    张三
    李四
    王五
'''

生成器

生成器函数:函数里面只要有yield关键字,那么这就是一个生成器函数
生成器函数最开始调用的时候,返回的是一个生成器对象,在python编译字节码的时候就产生了这个生成器对象
生成器函数也可以return一个值

生成器函数会在内部记录函数执行的字节码的位置,生成器函数也是分配在堆内存当中的
调用生成器函数,函数并不会马上执行,调用next方法或者用for驱动生成器的执行.
如果next方法取不到值了,则要给一个默认值,否则会报StopIteration的错误。
在生成器函数中,函数执行遇到yield会挂起,返回yield右边的值,直到下一次生成器再次被驱动。send方法也可以驱动生成器函数。

def foo():
    yield 1
    name = 'bobby'
    yield 2
    age = 18
    return 30


f = foo()
print(isinstance(f, Generator))
# 执行结果:True
print(next(f))
# 执行结果:1
print(next(f))
# 执行结果:2
print(next(f, 'Over'))

捕获生成器的返回值

def foo():
    yield 1
    name = 'bobby'
    yield 2
    age = 18
    return 30
f = foo()
while True:
    try:
        x = next(f)
        print(x)
    except StopIteration as e:
        print('StopIteration:',e.value)
        break
'''
执行结果:
    1
    2
    StopIteration: 30
'''s

相关文章

网友评论

      本文标题:迭代器和生成器

      本文链接:https://www.haomeiwen.com/subject/tdnkuhtx.html