欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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