python高级之迭代器

发布时间 2023-12-12 22:17:20作者: Xiao0101

迭代器

image

什么是迭代器

	迭代是python中访问集合元素的一种非常强大的一种方式。迭代器是一个可以记住遍历位置的对象,因此不会像列表那样一次性全部生成,而是可以等到用的时候才生成,因此节省了大量的内存资源。迭代器对象从集合中的第一个元素开始访问,直到所有的元素被访问完。迭代器有两个方法:iter()和next()方法。

可迭代的对象

	类似于list、tuple、str 等类型的数据可以使用for …… in…… 的循环遍历语法从其中依次拿到数据并进行使用,我们把这个过程称为遍历,也称迭代。python中可迭代的对象有list(列表)、tuple(元组)、str(字符串)set以及对于没有索引的字典、集合等非序列类型也适用。文件直接就是迭代器对象。
a = (1,)  # 元组
b = [1, 2]  # 列表
c = {}  # 空字典
d = ()  # 元组
s = set()
s1 = {None}  # 集合

print(type(c))  # 空集合 <class 'dict'>
print(type(d))  # <class 'tuple'>
print(type(s))  # 空集合 <class 'set'>

iter()、next()函数 for循环大体过程

iter()获取一个可迭代对象的迭代器

nums = [1, 2, 3, 4]	# 是可迭代对象
print(type(nums))	# <class 'list'>
nums_iter = iter(nums)	# 是迭代器
print(type(nums_iter))	# <class 'list_iterator'>

next()获取迭代器的数据

nums = [1, 2, 3, 4]	# 可迭代对象
nums_iter = iter(nums)	# 迭代器
num = next(nums_iter)
print(num)
num = next(nums_iter)
print(num)

for循环大体过程

for循环的过程可以通过上面的iter()和next()函数来实现,即:
1、先调用iter(),将nums当作实参,得到nums这个可迭代对象的迭代器
2、调用next(),将上一步得到的迭代器 进行取值
3、将上一步取出来的值 赋值给num这个变量
4、执行for循环体中的代码,print(num)
5、重复执行2/3/4步,当nums中所有数据都获取完毕后,会在下一次调用next的时候产生Stopiteration异常。只不过 for循环中自带了异常处理,当它遇到Stopiteration异常的时候,会自动结束for循环

自定义"迭代器"

iter 方法

迭代器是用来帮助我们记录每次迭代访问到的位置,当我们对迭代器使用 next()函数的时候,迭代器会向我们返回它所记录位置的下一个位置的数据。
实际上,在使用 next()函数的时候,调用的就是迭代器对象的 next 方法(Python2中是对象的next()方法)。
所以想要构造一个迭代器,就要实现它的 __next__方法。
但这还不够,python要求迭代器本身也是可迭代的,所以我们还要为迭代器实现 __iter__方法,而 __iter__方法要返回一个迭代器,迭代器自身正是一个迭代器,所以迭代器的 __iter__方法返回自身即可。
一个实现了__iter__方法和__next__方法的对象,就是迭代器,可以使用 isinstance() 判断一个对象是否是Iterator对象
from collections import Iterable
from collections import Iterator
 
 
class Classmate(object):
    """定义一个同学类"""
    def __init__(self):
        self.name = list()
        self.name_num = 0
 
    def add(self,name):
        self.name.append(name)
    
    def __iter__(self):
        pass
 
    def __next__(self):
       pass
 
class1 =  Classmate()
class1.add("张三")
class1.add("李四")
class1.add("王五")
 
print("判断是否是可迭代的对象:", isinstance(class1,Iterable))
print("判断是否是迭代器:", isinstance(class1,Iterator))

总结:如果定义类时,有__iter__方法,那么这个类创建出来的对象一定是可迭代对象

__next__方法

from collections.abc import Iterable
from collections.abc import Iterator

class MyList(object):
	"""自定义的一个可迭代对象"""
	def __init__(self):
		self.items = []

	def add(self, val):
		self.items.append(val)

	def __iter__(self):
		# 这个方法有两个功能
		# 1.标记用当前类创建出来的对象一定是 可迭代对象
		# 2.当调用iter()函数的时候 这个方法会被自动调用 它返回自己指定的哪个迭代器
		return MyIterator()

class MyIterator(object):
	"""自定义的供上面可迭代对象使用的一个迭代器"""
	def __init__(self):
		pass

	def __next__(self):
		# 这个方法有两个功能
		# 1.标记当前类创建出来的对象(当然还必须有__iter__方法)一定是迭代器
		# 2.当调用next()函数的时候 这个方法会被自动调用 它返回一个数据
		pass

	def __iter__(self):
		pass

mylist = MyList()	# 可迭代对象
mylist_iter = iter(mylist)	# 当对mylist调用iter()函数的时候,会自动调用MyList类中的__iter__方法,返回的就是mylist这个可迭代对象的迭代器

print("mylist是否是可迭代对象", isinstance(mylist, Iterable))	# True
print("mylist是否是迭代器", isinstance(mylist, Iterator))	# False

print("mylist_iter是否是可迭代对象", isinstance(mylist_iter, Iterable))	# True
print("mylist_iter是否是迭代器", isinstance(mylist_iter, Iterator))	# True

# next(mylist_iter)

总结

__iter__方法、__next__方法 与 iter()函数、next()函数的区别是,
当对一个可迭代对象调用iter()函数时,它会自动调用这个可迭代对象的__iter__方法,这个方法返回的对象当作迭代器
当对一个迭代器对象调用 next()函数时,它会自动调用这个迭代器对象的__next__方法,这个方法返回想要那个数据
迭代器对象 一定是 可迭代对象;可迭代对象不一定是迭代器

for…in… 循环的本质

1.先调用 iter()函数,它会自动调用可迭代对象中的 __iter__方法,此方法返回这个可迭代对象的 迭代器对象
2.对获取到的迭代器不断调用 next()函数,它会自动调用迭代器中的 __next__方法来获取下一个值
3.当遇到 StopIteration异常后循环结束
并不是只有for循环能接受可迭代对象,除了for循环外,list、tuple等也能接收

总结

1.凡是可作用于 for循环的对象都是 Iterable 类型;
2.但是可作用于 next()函数的对象都是 Iterator 类型;
3.集合数据类型如 list、dict、str 等是 Iterable 但不是 Iterator, 不过可以通过 iter() 函数获得一个 Iterator 对象