当前位置: 移动技术网 > IT编程>脚本编程>Python > python里for遍历执行流程及自定义可迭代器对象和迭代器

python里for遍历执行流程及自定义可迭代器对象和迭代器

2020年07月05日  | 移动技术网IT编程  | 我要评论

一、简单的模拟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

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网