爬虫日记之08对迭代器和可迭代对象的理解

爬虫日记之08迭代器和可迭代对象的理解

2022-3-6

1 写在前面

首先我们回顾一下在C语言中我们是如何遍历数组以及链表的~

遍历数组:

for (int i=0;i<sizeof(arrTest)/sizeof(int);i++)
{
    printf("%d\n",arrTest[i])
}

遍历链表:

NODE p=Head->next;
while(p)
{
    printf("%d ",p->data);
    p=p->next;
}

我们把数据和链表形象的看做“数据容器”,为了达到遍历的目的,我们需要访问容器中的每一个元素,而C语言这样的写法却很容易出现很多问题:

  • 针对不同的数据容器,采取的写法完全不同,可嫁接性低(自创词汇😁),也不利于书写和阅读;
  • 对编程者要求较高。比如只要循环条件写错了一点点,都会导致遍历功能无法实现
好的现在压力来到了新生代编程语言,以python为例,python是如何解决这个问题的呢?
那就让我们走进今天的主人公——迭代器。

2 迭代器的使用

首先我们来回顾一下在python中,我们是如何进行遍历操作的:

# 遍历列表
for e in List1:
    print(e)

# 遍历字典
for e in dic1:
    print(e)

# 遍历文件内容
for e in open("test.txt"):
    print(e)

我们可以惊喜地发现(强行惊喜🤷‍♀️),python中不同数据容器的遍历写法相同,更有利于我们的书写的理解。

而for语句之所以可以如此“万能”,正是因为背后有迭代器在默默地支持。

for语句在执行的时候,会在背后做两件事。

  • 第一件事,就是调用“数据仓库”位置对象的__iter__()方法;
  • 第二件事,把__iter()__ 方法的返回值当成一个对象,并且调用这个对象的__next__()方法;

在python中通过迭代器,我们可以使用相同的代码,对不同的数据容器进行遍历

列表、字典、文件都可以作为迭代器

我们可以通过代码查看某个对象是不是可迭代的

方法一

先对a进行定义,通过在a后加上.的方式,看该对象有无:对象.iter()的形式

a=2333
a._iter_() 
#通过观察是否报错来查对象a是否可以迭代
#也可以通过强行代入for语句来判断

方法二

使用isinstance方法来进行判断

from collections.abc import Iterable
a=2333
isinstance(a,Iterable)

list1=[1,2,3]
isinstance(list1,Iterable)#判断list1对象是否为可迭代对象
isinstance(list1,Iterator)#判断list1是否为迭代器

3 迭代器、生成器和可迭代对象

3.1 迭代器

3.1.1 迭代器类型的定义:

  1. 当类中定义了__iter__和__next__两个方法
  2. __iter__方法需要返回对象本身,即:self
  3. __next__方法,返回下一个数据,如果没有数据了,就需要弹出异常处理的语句

3.1.2 创建迭代器类型:

class IT(object):
    def __init__(self):
        self.counter=0

    def __iter__(self):
        return self

    def __next__(self):
        self.counter+=1
        if self.counter==3:
            raise StopIteration()
        return self.counter

3.2 生成器

3.2.1 生成器类型的定义:

刚才我们介绍了什么是迭代器,其实生成器本质上也是一种迭代器,不过他的创建方式简单一些,可以分为以下两步:
  1. 类中需要定义一个以yield关键字标识返回值的函数
  2. 调用刚刚创建的函数,即可创建一个生成器

3.2.2 创建生成器函数

def func():
    yield 1
    yield 2

3.2.3 创建生成器对象

生成器内部是根据生成器类generator创建的对象,生成器类的内部也表明了__iter__、__next__方法。

obj1=func()
#此处obj1即为生成器对象

3.3 可迭代对象

如果一个类中有__iter__方法且返回一个迭代器对象,我们就称这个类创建的对象为可迭代对象。

3.3.1 可迭代对象的创建

class Foo(object):
    def __iter__(self):
        return 迭代器对象(生成器对象)

obj=Foo() # 可迭代对象

for item in obj:
    print(item)
 # 循环可迭代对象时,内部先执行obj.__iter__并获取迭代器对象,然后不断地执行迭代器对象的next方法

3.4 一个小演示

如图,我们先创立了一个整数列表,然后通过dir()函数查看v1中的成员,我们可以看到出现了__iter__方法,而并没有__next__方法。


然后我们继续对v1进行iter()操作,命名为v2,继续通过dir()函数查看v2中的成员,我们可以找到__iter__方法和__next__方法。
说明v2是一个迭代器对象,而v1是一个可迭代对象。

写在后面

让自己写的类支持迭代:

  1. 给类加入__iter__()方法
  2. 上述方法返回的对象是迭代器(支持__iter__()和__next__())
    含泪推荐良心视频呜呜呜呜到底啥是迭代器?(官方文档证明,彻底搞懂迭代器)
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值