迭代器和生成器,使用生成器读取大文件

迭代器

迭代协议

# 可迭代类型 和 迭代器

"""
什么是迭代协议。
迭代器是什么?
    是访问集合类的一种方式,一般用来遍历数据。
    for循环可以遍历数据

迭代器和以下标的访问方式不一样,迭代器是不能返回的(后退)
alist[0] alist[2] alist[1] 是不行的
[ ]下标访问 背后的原理/协议 是 __getitem__

迭代器提供了一种惰性访问数据的方式
__iter__
"""

from collections.abc import Iterable,Iterator
"""
Iterable:__iter__

Iterator:迭代器 继承Iterable, __iter__ __next__
"""

list
# 只实现了__iter__,没有实现__next__
a = [1,2]
print(isinstance(a,Iterable))
print(isinstance(a,Iterator))

迭代器和可迭代对象区别

from collections.abc import Iterable,Iterator

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

iter_rator = iter(a)
print(isinstance(iter_rator,Iterable))
print(isinstance(iter_rator,Iterator))

"""
iter(传入一个可迭代对象)
返回一个迭代器

换一个说法
iter(传入一个实现__iter__的对象)
返回一个是实现了 __iter__ __next__的对象

"""

for循环与迭代

class Company(object):
    def __init__(self, employee_list):
        self.employee = employee_list
    def __iter__(self):
        yield 1
        yield 2
        yield 3
        # return iter([1,2,3,4])
    def __getitem__(self, item):
        return self.employee[item]

if __name__ == "__main__":
    company = Company(["tom", "bob", "jane"])
    for i in company:
        print(i)
"""
for循环 会去company 寻找__iter__协议,如果没有,退而求其次,选择 __getitem__
如果有iter,则会去选择__iter__
"""

自实现 迭代器

from collections.abc import Iterator

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


class Company(object):
    """
    使用自己的迭代器类
    """
    def __init__(self, employee_list):
        self.employee = employee_list

    def __iter__(self):
        return MyIterator(self.employee)
    
if __name__ == "__main__":
    company = Company(["tom", "bob", "jane"])
    my_itor = iter(company)
    for item in company:
        print (item)

生成器

生成器函数

def gen_func():
    yield 1
    yield 2
    yield 3

def func():
    return 1
    return 2

gen = gen_func() # 返回的是一个生成器对象
res= func()   # 返回的是1这个值
for i in gen:
    print(i)
"""
生成器对象,python编译字节码的时候就产生了,它发现了yield
"""

"""
惰性求值,延迟求值提供了可能
斐波那契
0 1 1 2 3 5 8
"""

def fib(index):
    """
    打印 斐波那契10位数
    """
    if index <=2:
        return 1
    else:
        return fib(index-1) +fib(index-2)

print(fib(10))

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))


# 使用生成器实现斐波那契
def fib3(index):
    n,a,b = 0,0,1
    while n<index:
        yield b
        a,b=b,a+b
        n+=1

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

生成器如何读取大文件

"""
读取一个500G的文件
f=open()
for line in f: 按照行读

如果这个500G文件只有一行,特殊分隔符 {|}
f = open()
f.read(4096) # 只有读出4096个字符
f.read(4096)
"""

#500G, 特殊 一行
def myreadlines(f, newline):
    """

    :param f: 文件句柄
    :param newline:分隔符
    """
    buf = "" #缓存,用来已经读出的数据量
    while True:
        while newline in buf:
            #查询缓存中的数据是否包含分隔符
            #如果存在 我们会把分隔符的位置找到
            pos = buf.index(newline)
            yield buf[:pos]
            buf = buf[pos + len(newline):]
        # setp1 读取4096个字符
        chunk = f.read(4096)

        if not chunk:
        #说明已经读到了文件结尾
            yield buf
            break
        buf += chunk

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

猜你喜欢

转载自blog.csdn.net/sunt2018/article/details/86577761