Python 高级编程 -- 迭代器和生成器

本文深入探讨Python中的迭代器和生成器概念,通过实例讲解如何创建自定义迭代器,解析生成器的工作原理,包括斐波那契数列生成及大文件高效读取策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 迭代器 Iterator 和可迭代的 Iterable

迭代器是访问集合内元素的一种方式, 一般用来遍历数据。迭代器和以下标的访问方式不一样, 迭代器是不能返回的, 迭代器提供了一种惰性方式数据的方式。
可迭代的 Iterable 表示这个对象是可以迭代的。

from collections.abc import Iterable, Iterator
a = [1,2]
iter_rator = iter(a)
print (isinstance(a, Iterable))
print (isinstance(iter_rator, Iterator))

2. 迭代器

2.1 第一个例子

使用 Python 内置的 iter 函数获得迭代器

from collections.abc import Iterator

class Company(object):
    def __init__(self, employee_list):
        self.employee = employee_list
	
	# 如果重写这个函数,需要返回迭代器,否则会报错
	# 优先调用 __iter__ 方法
    def __iter__(self):
        return MyIterator(self.employee)

	# 如果没有 __iter__ 方法,才会调用这个方法
    def __getitem__(self, item):
        return self.employee[item]

if __name__ == "__main__":
    company = Company(["tom", "bob", "jane"])
    
    my_itor = iter(company)

2.2 自定义迭代器

from collections.abc import Iterator

class Company(object):
    def __init__(self, employee_list):
        self.employee = employee_list

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

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

# 继承默认的 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

if __name__ == "__main__":
    company = Company(["tom", "bob", "jane"])
    
    # 结束迭代的时候会返回 StopIteration,for 语句接收到这个 except,进而结束循环
    for item in company:
        print(item)
	# 上面的 for 语句实现的功能可以用如下代码替代
	while True:
        try:
            print (next(my_itor))
        except StopIteration:
            pass

3. 生成器

函数里只要有yield关键字就是生成器函数。

3.1 一个例子

# 斐波那契数列
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)

3.2 读取只有单行的大文件

假设有个文件有 500G,并且只有一行,使用通常的方法都无法满足需求,我们使用每次读取 read(4096) 个字符,再加上 yield 方式完成需求。


def myreadlines(f, newline):
  buf = ""
  while True:
    while newline in buf:
      pos = buf.index(newline)
      yield buf[:pos]
      buf = buf[pos + len(newline):]
    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)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值