迭代器

为什么学习迭代器

如何for循环自定义实例对象

class Student:
  def __init__(self):
    self.students = []
  def add_student(self, name, age):
    self.students.append({
      "name": name,
      "age": age
    })

s = Student()
s.add_student('小明', 23)
s.add_student('小黑', 20)

# 如何实现for循环自定义实例对象?
for item in s:
  print(item)
# 报错
TypeError: 'Student' object is not iterable

什么是迭代?

迭代是访问集合元素的一种方式

# 字符串
my_str = 'hello'
for i in my_str:
  print(i)

# 列表
my_list = [1,2,3,4]
for i in my_list:
  print(i)

可迭代对象

可以被for-in遍历的都是可迭代对象

验证数据类型是否可以被迭代

from collections.abc import Iterable

# True 字符串
print(isinstance('12', Iterable))

# True 列表
print(isinstance([1,2], Iterable))

# True 元组
print(isinstance((1,2), Iterable))

# True 集合
print(isinstance({1,2}, Iterable))

# True 字典
print(isinstance({'name':'alex'}, Iterable))

# False 整数
print(isinstance(1, Iterable))

# False浮点数
print(isinstance(1.1, Iterable))

迭代器

迭代器是一个可以记住遍历的位置的对象。迭代器对象从第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。

可迭代对象的本质

可迭代对象进行迭代的过程,发现每迭代一次都会返回对象中的下一条数据,一直向后直到取完所有数据。

在每一次迭代过程中需要有一个『东西』来记住访问到第几条数据了,这个『东西』被称为迭代器(Iterator)

获取可迭代对象的迭代器

通过iter()能够得到一个可迭代对象的 迭代器

from collections.abc import Iterator

nums_list = [11, 22, 33, 44]
# 提取迭代器
nums_iter = iter(nums_list)

print(f"nums_list: {type(nums_list)}")  # nums_list: <class 'list'>
print(f"nums_iter: {type(nums_iter)}")  # nums_iter: <class 'list_iterator'>

print("nums_list", isinstance(nums_list, Iterator)) # nums_list False
print("nums_iter", isinstance(nums_iter, Iterator)) # nums_iter True

获取迭代器数据

通过iter()能够得到一个可迭代对象的 迭代器,可以通过next()函数多次提取迭代器中的数据

nums_list = [11, 22, 33, 44]
# 提取迭代器
nums_iter = iter(nums_list)

print(next(nums_iter))
print(next(nums_iter))
print(next(nums_iter))
print(next(nums_iter))
11
22
33
44

StopIteration异常

可迭代对象,我们可以通过iter()函数获取这些可迭代对象的迭代器。然后我们可以对获取到的迭代器不断使用next()函数来获取下一条数据

nums_list = [11, 22]
# 提取迭代器
nums_iter = iter(nums_list)

print(next(nums_iter))
print(next(nums_iter))
print(next(nums_iter))
11
22
# 取不到之后会报StopIteration错误
Traceback (most recent call last):
  File "提取可迭代对象的迭代器.py", line 19, in <module>
    print(next(nums_iter))
StopIteration

实现for循环

for循环的过程就是通过iter()提取可迭代对象的迭代器,然后通过next提取数值,直到StopIteration异常抛出后停止迭代

nums_list = [11, 22]
# 提取迭代器
nums_iter = iter(nums_list)

while True:
    try:
        print(next(nums_iter))
    except StopIteration as e:
        print(f"e: {e}")
        break
11
22
33
44
e: 

自定义"迭代器"

__iter__方法

拥有__iter__的对象一定是可迭代对象

from collections.abc import Iterable

class MyList1:
    pass

class MyList2:
    def __iter__(self):
        pass

m1 = MyList1()
m2 = MyList2()

# 检测是否是[可迭代对象]
print(isinstance(m1, Iterable)) # False
print(isinstance(m2, Iterable)) # True

__next__方法

在使用next()函数的时候,就是调用迭代器的__next__方法。

一个类实现了__iter____next__方法,生成的对象就是迭代器

from collections.abc import Iterable, Iterator

class MyIterable:
    def __iter__(self):
        # 当使用iter()函数时,会自动执行类中的__iter__方法,返回一个迭代器对象
        print(f"MyIterable iter")
        return MyIterator()

class MyIterator:
    def __iter__(self):
        pass
    def __next__(self):
        # 当使用next()函数时,会自动执行类中的__next__方法
        print(f"MyIterator next")

        
my = MyIterable()   # 获取可迭代对象
my_iter = iter(my)  # 获取迭代器

# 可迭代对象不一定是迭代器
print("my是否是可迭代对象 ", isinstance(my, Iterable)) # True
print("my是否是迭代器 ", isinstance(my, Iterator)) # False

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

next(my_iter)
MyIterable iter
my是否是可迭代对象  True
my是否是迭代器  False
my_iter是否是可迭代对象  True
my_iter是否是迭代器  True
MyIterator next

验证list

from collections.abc import Iterable, Iterator

l = [1,2,3]
l_iter = iter(l)
print("l是否是可迭代对象 ", isinstance(l, Iterable)) # True
print("l是否是迭代器 ", isinstance(l, Iterator)) # False
print("l_iter是否是可迭代对象 ", isinstance(l_iter, Iterable)) # True
print("l_iter是否是迭代器 ",isinstance(l_iter, Iterator)) # True
l是否是可迭代对象  True
l是否是迭代器  False
l_iter是否是可迭代对象  True
l_iter是否是迭代器  True

案列

迭代器

class Student:
    def __init__(self):
        self.index = 0
        self.students = []
        
    def add_student(self, name, age):
        info = {
            "name": name,
            "age": age
        }
        self.students.append(info)

    def __iter__(self):
        return self

    def __next__(self):
        if self.index < len(self.students):
            item = self.students[self.index]
            self.index += 1 
            return item 
        self.index = 0
        raise StopIteration
            

stu = Student()
stu.add_student('小明', 23)
stu.add_student('小黑', 20)

# 如何实现for循环自定义实例对象?
for item in stu:
    print(item)
{'name': '小明', 'age': 23}
{'name': '小黑', 'age': 20}

可迭代对象+迭代器

class Student:
    def __init__(self):
        self.students = []
        
    def add_student(self, name, age):
        info = {
            "name": name,
            "age": age
        }
        self.students.append(info)

    def __iter__(self):
        return StudentIter(self)

class StudentIter:
    def __init__(self, obj):
        self.obj = obj
        self.index = 0
    def __iter__(self):
        return self
    def __next__(self):
      	# 判断可迭代对象的长度
        if self.index < len(self.obj.students):
            item = self.obj.students[self.index]
            self.index += 1
            return item
        # 如果index超出长度,报StopIteration
        self.index = 0
        raise StopIteration

stu = Student()
stu.add_student('小明', 23)
stu.add_student('小黑', 20)
# 如何实现for循环自定义实例对象?
for item in stu:
    print(item)
{'name': '小明', 'age': 23}
{'name': '小黑', 'age': 20}
posted @ 2024-09-25 09:53  lxd670  阅读(20)  评论(0)    收藏  举报