Python学习之:一文搞懂 for 和迭代器对象、可迭代对象的关系,以及他们各自的用处

for 循环的底层逻辑

先来看下面这段代码:

lst = [1,2,3,4,5]
for i in lst:
    print(i)

在这里插入图片描述
for...in... 这个结构后面跟的 lst 一定是一个可迭代的对象,那可迭代对象有哪些呢:

print(issubclass(list,Iterable))
print(issubclass(dict,Iterable))
print(issubclass(str,Iterable))
print(issubclass(tuple,Iterable))
print(issubclass(int,Iterable))

在这里插入图片描述

可以看出,可迭代对象(Iterable)有:

  • 字典
  • 列表
  • 字符串
  • 元组
  • 集合

那么让我们继续回到 for 循环来看

当执行了 for 循环的语句之后,会调用 iter() 方法,将可迭代对象(in 后面的内容) 转化成一个迭代器对象,然后调用 迭代器对象中的 next() 方法,将迭代器中的对象一个个的顺序输出,如下图代码中所示的对比效果:

lst = [1,2,3,4,5]
for i in lst:
    print(i)


lst1 = [1,2,3,4,5]
iterator = iter(lst1)		# 将可迭代对象lst1 转换成迭代器对象 iterator
while iterator:
    try:
        print(next(iterator))	# 当 iterator 不为空的时候,使用next() 方法不断打印其中的值
    except StopIteration:	# 当next() 到最后一个元素的时候会抛出异常 StopIteration,我们捕捉这个异常,并且退出循环;以此完成了for循环同样的效果
        break

其实这整个过程分成了两步:

  • lst1是一个容器,这个容器中通过开辟内存而存放了 1, 2, 3,4, 5 这些元素
  • 将容器中赋予 __iter__ 这个方法,这个容器才能够呈现出把每个元素进行操作的功能

所以,我们拿掉列表的容器功能,不让他存储数据,那么他不就变成了一个简单的可迭代对象了么~
但是!!!!如果没有给这个类中加入 __next__ 方法,是不可以对其进行 iter() 而变成迭代器对象的。

class MyList:
    def __init__(self):
        self.value = 1

    def __iter__(self):
        return self

lst = MyList()

print(isinstance(lst, Iterable))
lst = iter(lst)
print(isinstance(lst,Iterator))

在这里插入图片描述

我们还可以把 next 方法加进去,然后对这个可迭代的对象进行 iter() 操作,使他变成一个迭代器对象,例如:

class MyList:
    def __init__(self):
        self.value = 1

    def __iter__(self):
        return self

    def __next__(self):
        pass

lst = MyList()

print(isinstance(lst, Iterable))
lst = iter(lst)
print(isinstance(lst,Iterator))

在这里插入图片描述

所以我们可以得到很浅显的结论:

  • 一个对象可不可迭代(Iterable)决定了能不能对其使用 for 循环
  • 一个对象是不是迭代器对象(Iterator)决定了能不能单独那他来进行功能实现。
  • 使用 Iterable 的性质,只有放在容器里才有意义,没有容器的功能,只有可迭代的性质是毫无用处的。但是 iterator 不需要自身有容器就可以完成很多功能。

直接这么说可能不够直观,我们通过下面的例子来写个功能来看一下~

  • 现在我要用两个可迭代对象 lst1 和 lst2 和他们的容器功能来生成一个斐波那契数列
  • 我也可以用一个迭代器直接生成斐波那契数列,而不需要占用额外的内存空间

方法一:使用可迭代对象 + 容器 来完成斐波那契数列

lst = [0,1]

for i in range(10):
    lst.append(lst[-1]+lst[-2])
print(lst[1:])

在这里插入图片描述

方法二:直接创建迭代器来完成斐波那契数列


class Feb:
    def __init__(self,length):  # length取决于用户想产生多长的斐波那契数列
        self.a = 0      # a 和 b 是数列初始值
        self.b = 1
        self.length = length

    def __iter__(self):     # 自身就是可迭代的,所以这个函数返回自身即可
        return self

    def __next__(self):     # 核心部分:如何处理每一个迭代的结果
        while self.length > 0:
            self.length -= 1
            self.a, self.b = self.a + self.b, self.a
            return self.a
           
if __name__ == '__main__':
    s = Feb(8)
    print(next(s))
    print(next(s))
    print(next(s))
    print(next(s))
    print(next(s))
    print(next(s))
    print(next(s))
    print(next(s))
    print(next(s))

在这里插入图片描述
当迭代器对象的所有元素输出后,剩下的就是 None了

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

暖仔会飞

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值