python里for遍历执行流程及自定义可迭代器对象和迭代器
程序员文章站
2023-11-26 09:09:16
一、简单的模拟for执行过程执行过程:for temp in xxx_obj:pass1.先判断xxx_obj是否可以迭代的对象;2.如果xxx_obj是可迭代的,自动调用iter函数,iter函数自动调用xxx_obj对象的__iter__方法;3.如果xxx_obj对象的__iter__方法的返回值是一个迭代器,之后for通过自动调用next函数来间接调用迭代器里的__next__函数来取出数据.模拟的代码如下:用两个类模拟,一个是创建可迭代对象的类,一个是创建迭代器的类。from...
一、简单的模拟for执行过程
执行过程:
for temp in xxx_obj:
pass
1.先判断xxx_obj是否可以迭代的对象;
2.如果xxx_obj是可迭代的,自动调用iter函数,iter函数自动调用xxx_obj对象的__iter__方法;
3.如果xxx_obj对象的__iter__方法的返回值是一个迭代器,之后for通过自动调用next函数来间接调用迭代器里的__next__函数来取出数据.
模拟的代码如下:用两个类模拟,一个是创建可迭代对象的类,一个是创建迭代器的类。
from collections.abc import Iterable, Iterator
# 迭代器类
class ClassIterator(object):
def __init__(self):
pass
def __iter__(self):
pass
def __next__(self):
"""同时有__iter__和__next__的类创建的对象是一个迭代器"""
return "nice"
# 可迭代对象类
class Classmate(object):
def __init__(self):
self.names = list()
def add(self, name):
self.names.append(name)
def __iter__(self):
"""只要添加__iter__方法,该类创建的对象就是可以迭代的对象"""
return ClassIterator() # 返回一个迭代器
def main():
classmate = Classmate()
# 模拟for执行
# 1. 判断是否是可迭代的对象
print("classmate是否是可以迭代的对象:", isinstance(classmate, Iterable))
# 2.iter调用可迭代对象的__iter__,并返回一个迭代器
if isinstance(classmate, Iterable):
# iter会调用实参classmate的__iter__,返回一个迭代器
classmate_iterator = iter(classmate)
print("classmate_iterator是否是迭代器:", isinstance(classmate_iterator, Iterator))
# 3.next调用迭代器的__next__,返回数据
if isinstance(classmate_iterator, Iterator):
# next会调用实参classmate_iterator的__next__
print(next(classmate_iterator))
if __name__ == "__main__":
main()
代码执行结果:
classmate是否是可以迭代的对象: True
classmate_iterator是否是迭代器: True
nice
二、自定义可迭代的类:在类里实现__iter__和__next__方法
from collections.abc import Iterable, Iterator
class Classmate(object):
def __init__(self):
self.names = list() # 存储要遍历的数据
self.current_num = 0 # 下标,记录当前遍历的位置
def add(self, name):
self.names.append(name)
def __iter__(self):
return self # 自身就是迭代器,所以返回self自己,返回谁下一步就调用谁的__next__
def __next__(self):
# 只要容器里的数据没有被取完,for就一直调用__next__
if self.current_num < len(self.names):
ret = self.names[self.current_num]
self.current_num += 1
return ret
else:
raise StopIteration # 遍历结束(取完数据),抛出停止遍历的异常
def main():
# 自定义类创建可迭代的对象
classmate = Classmate()
classmate.add(10)
classmate.add(20)
classmate.add(30)
# 遍历自定义类创建的对象
for temp in classmate:
print(temp)
if __name__ == "__main__":
main()
注:如果上面的代码不好理解,可以先看下面的代码
from collections.abc import Iterable, Iterator
# 迭代器类
class ClassIterator(object):
def __init__(self, another_obj):
# 将要遍历的对象赋值给迭代器的self.obj
self.obj = another_obj # 存储待遍历的对象
self.current_num = 0 # 下标,记录当前遍历到哪个元素
def __iter__(self):
pass
def __next__(self):
"""同时有__iter__和__next__的类创建的对象是一个迭代器"""
if self.current_num < len(self.obj.names):
ret = self.obj.names[self.current_num]
self.current_num += 1
return ret
else:
raise StopIteration # 抛出异常,遍历结束
# 可迭代对象类
class Classmate(object):
def __init__(self):
self.names = list()
def add(self, name):
self.names.append(name)
def __iter__(self):
"""只要添加__iter__方法,该类创建的对象就是可以迭代的对象"""
return ClassIterator(self) # 创建返回一个迭代器,要遍历self,所以要传递self
def main():
classmate = Classmate()
classmate.add(10)
classmate.add(20)
classmate.add(30)
for temp in classmate:
print(temp)
if __name__ == "__main__":
main()
三、使用迭代器节约内存空间
迭代器作用:使用迭代器,可以不用预先知道要分配多大的空间,当数据规模比较大时,如果使用列表、元组等来存储数据,需要开辟很大的内存空间。而使用迭代器可以不用分配这么大的空间,迭代器是在不断迭代遍历的时候生成数据。迭代器不存储要遍历的数据,而是存储产生该数据的方式。一般用于遍历有规律的数据。
例子:遍历斐波那契数列
class Fibonacci(object):
def __init__(self, all_num):
self.all_num = all_num # 要创建多少个数
self.current_num = 0 # 当前已经创建的个数
self.a = 0
self.b = 1
def __iter__(self):
return self
def __next__(self):
"""只要不抛出异常,for就会一直调用__next__"""
if self.current_num < self.all_num:
ret = self.a
self.a, self.b = self.b, self.a+self.b
self.current_num += 1
return ret
else:
raise StopIteration
if __name__ == "__main__":
all_cnt = 8
fib = Fibonacci(all_cnt)
cnt = 1
for num in fib:
# 将__next__返回的结果赋值给num
if cnt < all_cnt:
print(num, end=",")
else:
print(num)
cnt += 1
结果:
0,1,1,2,3,5,8,13
本文地址:https://blog.csdn.net/weixin_43971252/article/details/107095873
上一篇: 我的前半生最经典语录大全!