ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Python面向对象:__iter__与__next__创建可迭代对象

2026/9/6 8:19:11 拓冰建站 浏览量
Python面向对象:__iter__与__next__创建可迭代对象 Python面向对象__iter__与__next__创建可迭代对象一、开篇让你的对象能被for循环你每天都在用for循环遍历列表、字典、文件。但你是否想过——为什么你能for x in my_object答案是迭代器协议__iter__和__next__。⌨️ 先看核心概念# 可迭代对象Iterable实现了__iter__可以被for循环使用# 迭代器Iterator实现了__iter__和__next__逐个产出元素# 内置的例子my_list[1,2,3]# 1. my_list是可迭代对象——有__iter__print(hasattr(my_list,__iter__))# True# 2. 调用iter()获得迭代器iteratoriter(my_list)# 等价于 my_list.__iter__()print(type(iterator))# class list_iterator# 3. 调用next()获取下一个元素print(next(iterator))# 1print(next(iterator))# 2print(next(iterator))# 3# print(next(iterator)) # StopIteration —— 迭代结束二、创建自定义迭代器2.1 通过__iter__和__next__classCountdown:倒计时迭代器def__init__(self,start):self.startstart self.currentstartdef__iter__(self):返回迭代器自身returnselfdef__next__(self):返回下一个元素ifself.current0:raiseStopIteration# 迭代结束的信号valueself.current self.current-1returnvalue# 使用forninCountdown(5):print(n,end )# 5 4 3 2 1print()print(list(Countdown(3)))# [3, 2, 1]# ⚠️ 上述实现的限制只能迭代一次cdCountdown(3)print(list(cd))# [3, 2, 1]print(list(cd))# [] —— 第二次为空current已经到0了2.2 分离可迭代对象和迭代器# ✅ 更好的设计可迭代对象每次产生新的迭代器# 这样可以多次迭代classCountdownIterable:倒计时——可多次迭代def__init__(self,start):self.startstartdef__iter__(self):每次调用返回一个新的迭代器returnCountdownIterator(self.start)classCountdownIterator:倒计时迭代器——不需要在外部直接使用def__init__(self,start):self.currentstartdef__iter__(self):returnselfdef__next__(self):ifself.current0:raiseStopIteration valueself.current self.current-1returnvalue# 现在可以多次迭代了cdCountdownIterable(3)print(list(cd))# [3, 2, 1]print(list(cd))# [3, 2, 1] —— 没问题每次迭代都是新的迭代器三、用生成器简化实现3.1 __iter__返回生成器# 使用yield可以极大简化__iter__的实现# 不需要单独写__next__classFibonacci:斐波那契数列——使用生成器的__iter__def__init__(self,max_count):self.max_countmax_countdef__iter__(self):生成器函数——自动创建迭代器a,b0,1for_inrange(self.max_count):yielda a,bb,ab# 使用fibFibonacci(10)print(list(fib))# [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]# 可以多次迭代print(list(fib))# [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]# 这是最Pythonic的做法# 用yield在__iter__中定义迭代逻辑# 简洁、可读、正确自动支持多次迭代3.2 实际应用分页遍历classPaginator:分页器——自动按页遍历大数据集def__init__(self,items,page_size10):self.itemsitems self.page_sizepage_sizedef__iter__(self):按页产出数据foriinrange(0,len(self.items),self.page_size):pageself.items[i:iself.page_size]page_numi//self.page_size1total_pages(len(self.items)self.page_size-1)//self.page_sizeyield{page:page_num,total_pages:total_pages,items:page,has_next:page_numtotal_pages,}def__len__(self):返回总页数return(len(self.items)self.page_size-1)//self.page_size# 使用datalist(range(1,26))# 25条数据paginatorPaginator(data,page_size10)forpageinpaginator:print(f第{page[page]}/{page[total_pages]}页:{page[items]})# 第1/3页: [1, 2, ..., 10]# 第2/3页: [11, 12, ..., 20]# 第3/3页: [21, 22, 23, 24, 25]四、实战案例4.1 日期范围迭代器fromdatetimeimportdatetime,timedeltaclassDateRange:日期范围——可以for循环遍历每一天def__init__(self,start_date,end_date):self.start_datestart_date self.end_dateend_datedef__iter__(self):currentself.start_datewhilecurrentself.end_date:yieldcurrent currenttimedelta(days1)def__contains__(self,date):支持 in 操作符returnself.start_datedateself.end_datedef__len__(self):返回天数return(self.end_date-self.start_date).days1# 使用startdatetime(2024,6,1)enddatetime(2024,6,10)date_rangeDateRange(start,end)# for循环遍历fordindate_range:ifd.weekday()5:# 周末print(f{d.strftime(%Y-%m-%d)}是周末)# in操作check_datedatetime(2024,6,5)print(f{check_date.date()}{在ifcheck_dateindate_rangeelse不在}范围内)# 2024-06-05 在范围内# lenprint(f共{len(date_range)}天)4.2 文件行迭代器带行号classLineNumberedFile:读取文件——自动添加行号def__init__(self,filepath,encodingutf-8):self.filepathfilepath self.encodingencodingdef__iter__(self):逐行产出每行带行号withopen(self.filepath,r,encodingself.encoding)asf:forline_num,lineinenumerate(f,1):yield{number:line_num,content:line.rstrip(\n),length:len(line.rstrip(\n)),is_empty:line.strip(),}# 使用# reader LineNumberedFile(data.txt)# for line_info in reader:# if not line_info[is_empty]:# print(f第{line_info[number]}行({line_info[length]}字): # f{line_info[content][:50]}...)五、总结实现__iter__让你的对象可以被for循环使用——这是Python集合生态的通行证。核心要点__iter__返回迭代器——让对象可迭代__next__产出下一个元素——迭代器耗尽抛StopIteration最简单的实现——在__iter__中用yield分离可迭代对象和迭代器——支持多次迭代实现后免费获得for循环、list()、in操作部分、sum()等✅最佳实践在__iter__中用生成器yield——代码简洁且自动支持多次迭代。