Python 迭代、可迭代对象、迭代器、生成器总结

迭代

对list、tuple、str等类型的数据使用for...in...的循环语法从其中依次拿到数据进行使用,我们把这样的过程称为遍历,也叫迭代

可迭代对象

不是所有对象都能使用for ..in ,比如数字10,把可以通过for...in...这类语句迭代读取一条数据供我们使用的对象称之为可迭代对象(Iterable)

判断是否是可迭代对象

from collections.abc import Iterable

print(isinstance("hello", Iterable))  # True
print(isinstance({"name": "zhangsan", "age": 18}, Iterable))  # True
print(isinstance([11, 22, 33], Iterable))  # True
print(isinstance((10, 20, 30), Iterable))  # True
print(isinstance({1, 9, 0, 88}, Iterable))  # True
print(isinstance(10.5, Iterable))  # False

可迭代对象的本质:具备了__iter__方法的对象,就是一个可迭代对象

#该类没有实现__iter__方法,所以不是可迭代对象
class Student:
    def __init__(self, age):
        self.age = age


print(isinstance(Student(8), Iterable))  # False
#重写了__iter__方法
class Student:
    def __init__(self, age):
        self.age = age

    def __iter__(self):
        return self


print(isinstance(Student(8), Iterable))  # True

迭代器

本质就是一个实现了__iter__方法和__next__方法的对象,就是迭代器

判断是否是迭代器

from collections.abc import Iterator, Iterable

# 判断是否是迭代器,可迭代对象是Iterable不是迭代器(Iterator)
print(isinstance("hello", Iterator))  # False
print(isinstance({"name": "zhangsan", "age": 18}, Iterator))  # False
print(isinstance([11, 22, 33], Iterator))  # False
print(isinstance((10, 20, 30), Iterator))  # False
print(isinstance({1, 9, 0, 88}, Iterator))  # False
print(isinstance(10.5, Iterator))  # False
print("-----------------------------------------------")

# 调用一个对象的__iter__方法,或者调用iter()内置函数,可以获取到一个可迭代对象的迭代器,只能是可迭代对象才能调用,否则报错
print(isinstance(iter("hello"), Iterator))  # True
print(isinstance(iter({"name": "zhangsan", "age": 18}), Iterator))  # True
print(isinstance([11, 22, 33].__iter__(), Iterator))  # True
print(isinstance((10, 20, 30).__iter__(), Iterator))  # True
print(isinstance(iter({1, 9, 0, 88}), Iterator))  # True
# print(isinstance(iter(10.5), Iterator))  # 报错 TypeError: 'float' object is not iterable
print("-----------------------------------------------")


class Student:
    def __init__(self, age):
        self.age = age

    def __iter__(self):
        return self

    def __next__(self):
        pass


print(isinstance(Student(8), Iterator))  # True

for ...in...循环的本质

for item in Iterable 循环的本质就是①先通过iter()函数获取可迭代对象Iterable的迭代器,②然后对获取到的迭代器不断调用next()方法来获取下一个值并将其赋值给item,③当遇到StopIteration的异常后循环结束

生成器

利用迭代器,我们可以在每次迭代获取数据(通过next()方法)时按照特定的规律进行生成。但是我们在实现一个迭代器时,关于当前迭代到的状态需要我们自己记录,进而才能根据当前状态生成下一个数据。为了达到记录当前状态,并配合next()函数进行迭代使用,我们可以采用更简便的语法,即生成器(generator)。生成器是一类特殊的迭代器
总结就是:

  • 生成器是一类特殊的迭代器
  • 只要在def中有yield关键字的 就称为 生成器

创建生成器方法1

g = (i * 2 for i in range(5))
print(g)  # <generator object <genexpr> at 0x0000000002581CF0>
print(next(g))  # 0
print(next(g))  # 2
print(next(g))  # 4
print(next(g))  # 6
print(next(g))  # 8
print(next(g))  # 报错 StopIteration

#也可以使用for i in g 的方式遍历

创建生成器方法2

def generate_test(n):
    result = []
    for i in range(n):
        result.append(i * 2)
        yield result


g = generate_test(5)
print(g)
print(next(g))  # [0]
print(next(g))  # [0,2]
print(next(g))  # [0,2,4]
print(g.__next__())  # [0,2,4,6]也可以使用__next__方法,只是用的相对较少
print(g.__next__())  # [0,2,4,6,8]也可以使用__next__方法,只是用的相对较少
#print(g.__next__()) # 报错  StopIteration

#也可以使用for in
for i in g:
    print(i)

image

生成器总结

  • 使用了yield关键字的函数不再是函数,而是生成器。(使用了yield的函数就是生成器)
  • yield关键字有两点作用:
    • 保存当前运行状态(断点),然后暂停执行,即将生成器(函数)挂起
    • 将yield关键字后面表达式的值作为返回值返回,此时可以理解为起到了return的作用
      可以使用next()函数让生成器从断点处继续执行,即唤醒生成器(函数)
posted @ 2023-09-06 19:30  弩哥++  阅读(12)  评论(0编辑  收藏  举报