细说 python 迭代器和生成器

迭代器与生成器


一. 迭代

1. 迭代的概念

使用for循环遍历取值的过程叫做迭代,比如:使用for循环遍历列表获取值的过程

for value in [2, 3, 4]:
    print(value)
2. 可迭代对象

使用for循环遍历取值的对象叫做可迭代对象, 比如:列表、元组、字典、集合、range、字符串

3. 判断对象是否为可迭代对象
# 元组,列表,字典,字符串,集合,range都是可迭代对象
from collections import Iterable

# 判断对象是否是指定类型
result = isinstance((3, 5), Iterable)
print("元组是否是可迭代对象:", result)

result = isinstance([3, 5], Iterable)
print("列表是否是可迭代对象:", result)

result = isinstance({"name": "张三"}, Iterable)
print("字典是否是可迭代对象:", result)

result = isinstance("hello", Iterable)
print("字符串是否是可迭代对象:", result)

result = isinstance({3, 5}, Iterable)
print("集合是否是可迭代对象:", result)

result = isinstance(range(5), Iterable)
print("range是否是可迭代对象:", result)

result = isinstance(5, Iterable)
print("整数是否是可迭代对象:", result)

# 提示: 以后还根据对象判断是否是其它类型,比如以后可以判断函数里面的参数是否是自己想要的类型
result = isinstance(5, int)
print("整数是否是int类型对象:", result)

class Student(object):
    pass

stu = Student()
result = isinstance(stu, Iterable)

print("stu是否是可迭代对象:", result)

result = isinstance(stu, Student)

print("stu是否是Student类型的对象:", result)
4. 自定义可迭代对象

自定义可迭代对象: 在类里面定义iter方法创建的对象就是可迭代对象

二. 迭代器

1. 自定义迭代器对象

自定义迭代器对象: 在类里面定义iternext方法创建的对象就是迭代器对象

from collections import Iterable
from collections import Iterator

# 自定义可迭代对象: 在类里面定义__iter__方法创建的对象就是可迭代对象
class MyList(object):

    def __init__(self):
        self.my_list = list()

    # 添加指定元素
    def append_item(self, item):
        self.my_list.append(item)

    def __iter__(self):
        # 可迭代对象的本质:遍历可迭代对象的时候其实获取的是可迭代对象的迭代器, 然后通过迭代器获取对象中的数据
        my_iterator = MyIterator(self.my_list)
        return my_iterator


# 自定义迭代器对象: 在类里面定义__iter__和__next__方法创建的对象就是迭代器对象
class MyIterator(object):

    def __init__(self, my_list):
        self.my_list = my_list

        # 记录当前获取数据的下标
        self.current_index = 0

        # 判断当前对象是否是迭代器
        result = isinstance(self, Iterator)
        print("MyIterator创建的对象是否是迭代器:", result)

    def __iter__(self):
        return self

    # 获取迭代器中下一个值
    def __next__(self):
        if self.current_index < len(self.my_list):
            self.current_index += 1
            return self.my_list[self.current_index - 1]
        else:
            # 数据取完了,需要抛出一个停止迭代的异常
            raise StopIteration


my_list = MyList()
my_list.append_item(1)
my_list.append_item(2)
result = isinstance(my_list, Iterable)

print(result)

for value in my_list:
    print(value)

执行结果:

True
MyIterator创建的对象是否是迭代器: True
1
2
2. iter()函数和next()函数
  • iter函数: 获取可迭代对象的迭代器,会调用可迭代对象身上的iter方法
  • next函数: 获取迭代器中下一个值,会调用迭代器对象身上的next方法
3. for循环的本质
  • 遍历的是可迭代对象

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

  • 遍历的是迭代器

    for item in Iterator 循环的迭代器,不断调用next()方法来获取下一个值并将其赋值给item,当遇到StopIteration的异常后循环结束。

4. 利用斐波那契数列实现迭代器
class Fibonacci(object):

    def __init__(self, num):
        # num:表示生成多少fibonacci数字
        self.num = num
        # 记录fibonacci前两个值
        self.a = 0
        self.b = 1
        # 记录当前生成数字的索引
        self.current_index = 0

    def __iter__(self):
        return self

    def __next__(self):
        if self.current_index < self.num:
            result = self.a
            self.a, self.b = self.b, self.a + self.b
            self.current_index += 1
            return result
        else:
            raise StopIteration


fib = Fibonacci(5)
# value = next(fib)
# print(value)

for value in fib:
    print(value)

三. 生成器

1. 生成器的概念

生成器是一类特殊的迭代器,它不需要再像上面的类一样写iter()和next()方法了, 使用更加方便,它依然可以使用next函数和for循环取值

2. 创建生成器的两种方式
  • 第一种方法很简单,只要把一个列表生成式的 [ ] 改成 ( )
  • 在def函数里面看到有yield关键字那么就是生成器

总结:

在使用生成器实现的方式中,我们将原本在迭代器next方法中实现的基本逻辑放到一个函数中来实现,但是将每次迭代返回数值的return换成了yield,此时新定义的函数便不再是函数,而是一个生成器了。
简单来说:只要在def中有yield关键字的 就称为 生成器

3.yield 和 return 对比
  • 使用了yield关键字的函数不再是函数,而是生成器。(使用了yield的函数就是生成器)
  • 代码执行到yield会暂停,然后把结果返回出去,下次启动生成器会在暂停的位置继续往下执行
  • 每次启动生成器都会返回一个值,多次启动可以返回多个值,也就是yield可以返回多个值
  • return只能返回一次值,代码执行到return语句就停止迭代,抛出停止迭代异常
4. 使用 send方法可以为生成器传参

注意:如果第一次启动生成器使用send方法,那么参数只能传入None,一般第一次启动生成器使用next函数
总结:

生成器创建有两种方式,一般都使用yield关键字方法创建生成器
yield特点是代码执行到yield会暂停,把结果返回出去,再次启动生成器在暂停的位置继续往下执行

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值