[Python笔记08] 迭代器和生成器

1.Python迭代协议

  • 迭代器是访问集合内元素的一种方式, 一般用来遍历数据。
  • 迭代器和以下标的访问方式不一样,迭代器是不能返回的,迭代器提供了一种惰性方式数据的方式。
  • 迭代协议实际上就是__iter__,两个要求:可迭代;迭代器。
from collections.abc import Iterable, Iterator

a = [1, 2]
iter_rator = iter(a)
print(isinstance(a, Iterable))
print(isinstance(a, Iterator))
print(isinstance(iter_rator, Iterator))

输出结果

True
False
True

list只是可迭代,而不是一个迭代器。

2.迭代器和可迭代对象

这段代码能打印出结果,就是因为在Company内部自动生成了一个__iter__方法。

class Company(object):
    def __init__(self, employee_list):
        self.employee = employee_list
        
    def __getitem__(self, item):
        return self.employee[item]
    
    
if __name__ == "__main__":
    company = Company(["tom", "bob", "jane"])
    for item in company:
        print (item)

输出结果

tom
bob
jane

下面模拟实现一个迭代器

from collections.abc import Iterator

class Company(object):
    def __init__(self, employee_list):
        self.employee = employee_list
        
    def __iter__(self):
        return MyIterator(self.employee)
    
class MyIterator(Iterator):
    def __init__(self, employee_list):
        self.iter_list = employee_list
        self.index = 0
    
    def __next__(self):
        #真正返回迭代值的逻辑
        try:
            word = self.iter_list[self.index]
        except IndexError:
            raise StopIteration
        self.index += 1
        return word
        
        
if __name__ == "__main__":
    company = Company(["tom", "bob", "jane"])
    my_itor = iter(company)
    while True:
        try:
            print(next(my_itor))
        except StopIteration:
            pass

输出结果

tom
bob
jane

3.生成器函数

只要函数里有yield,那么这个函数就是生成器函数。

yield和return的区别:

def gen_func():
    yield 1

def func():
    return 1

if __name__ == "__main__":
    #生成器对象,在python编译字节码的时候就产生了
    gen = gen_func()
    print(gen)
    re = func()
    print(re)

输出结果

<generator object gen_func at 0x0000025AE4983048>
1

yield返回的是一个生成器,return返回的是返回值。

def gen_func():
    yield 1
    yield 2
    yield 3

def func():
    return 1

if __name__ == "__main__":
    #生成器对象,在python编译字节码的时候就产生了
    gen = gen_func()
    for value in gen:
        print(value)

输出结果

1
2
3

一个函数里不能在return后面再加一个return,但是可以有多个yield。return之后函数的调用就结束了,而yield调用之后还可以继续yield。

生成器函数为惰性求值,延迟求值提供了可能。下面来看看生成器函数的一个使用。
(1)斐波那契数列普通写法

def fib(index):
    if index <= 2:
        return 1
    else:
        return fib(index-1) + fib(index-2)
    
print(fib(10))

输出结果

55

(2)斐波那契数列列表写法

def fib2(index):
    re_list = []
    n, a, b = 0, 0, 1
    while n < index:
        re_list.append(b)
        a, b = b, a+b
        n += 1
    return re_list

print(fib2(10))

输出结果

[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]

(3)斐波那契数列yield写法

def gen_fib(index):
    n, a, b = 0, 0, 1
    while n < index:
        yield b
        a, b = b, a+b
        n += 1

for data in gen_fib(10):
    print(data)

输出结果

1
1
2
3
5
8
13
21
34
55

yield可以把整个计算的过程展现出来,它只在计算的时候消耗内存,大大节省了内存。

4.yield读取大文件

input.txt文件内容

Prior to beginning tutoring sessions{|}, I ask new students to fill{|} out a brief self-assessment{|} where they rate their{|} understanding of various Python concepts. Some topics ("control flow with if/else" or "defining and using functions") are understood by a majority of students before ever beginning tutoring. There are a handful of topics, however, that almost all{|} students report having no knowledge or very limited understanding of. Of these

读取代码

def myreadlines(f, newline):
    buf = ""  #已经读出的数据
    while True:
        while newline in buf:   #如果分隔符在buf中
            pos = buf.index(newline)    #分隔符的位置
            yield buf[:pos]   #返回一行内容
            buf = buf[pos + len(newline) : ]    #下一行开始往后的内容
        chunk = f.read(4096)    #一次读取4096个字符
        
        if not chunk:
            #说明已经读到了文件结尾
            yield buf
            break
        buf += chunk

with open("input.txt") as f:
    for line in myreadlines(f, "{|}"):  #分隔符为{|}
        print(line)

输出结果

Prior to beginning tutoring sessions
, I ask new students to fill
 out a brief self-assessment
 where they rate their
 understanding of various Python concepts. Some topics ("control flow with if/else" or "defining and using functions") are understood by a majority of students before ever beginning tutoring. There are a handful of topics, however, that almost all
 students report having no knowledge or very limited understanding of. Of these

你可能感兴趣的:(Python高级)