「Python网络编程」迭代器和生成器(四)

博主前言:

「2020本来是充满希望,收获幸福的一年。可没想到这一年的开始就如此的惨烈、痛苦。在此,博主真诚的祝福那些身处在抗疫一线的白衣天使们能够平稳健康,给他(她)们致以最崇高的敬意」
这篇博客讲述Python中的迭代器和生成器,内容较抽象,希望读者结合代码好好理解。

1. 迭代器

迭代是重复反馈过程的活动,其目的通常是为了逼近所需目标或结果。
每一次对过程的重复称为一次“迭代”,而每一次迭代得到的结果会作为下一次迭代的初始值。
在计算机中重复执行程序中的循环,直到满足某条件为止,亦称为迭代
在这里插入图片描述

1.1 iter()

Python语言中,在定义一个类时,如果在类中定义了iter()函数,
那么这个类就是可迭代的类
由这个类所实例化的对象就是可迭代的对象
在Python语言中,可调用collections模块的Iterable中的isinstance()函数判断当前对象是否可迭代。

from collections import Iterable

class IterableClass(object):
	"""定义一个可迭代的类"""
    def __init__(self,name,nubmer):		# 构造函数
        self.name = name
        self.number = nubmer

    def __iter__(self):		# 定义iter函数,伪代码
        pass

def main():
    test = IterableClass("tomato",2020)
    print("判断test是否可迭代:%s" % isinstance(test,Iterable))

if __name__ == '__main__':
    main()

当我们运行上述代码时,结果如下:
在这里插入图片描述
可当我们把定义的iter函数注释掉后再运行时代码,结果会大相径庭。

# def __iter__(self):		# 定义iter函数,伪代码
#        pass

在这里插入图片描述
由此可知:
当类中定义了iter函数时,那么由该类实例化的对象是可迭代的。
当类中没有定义iter函数时,由该类实例化的对象就不可迭代(例整型)。

1.2 next()

在类定义时,同时定义了iter函数和next函数的类,其所实例化的对象称为迭代器对象。
可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator
在Python语言中,可调用collections模块的Iterable中的isinstance()函数判断当前对象是否为迭代器对象(代码实现如上段)
接下来,我们在定义一个迭代器类。

from collections import Iterable

class IteratorClass(object):
	"""定义一个迭代器类"""
    def __init__(self):		# 构造函数
        self.g_number = 0
        self.name = list()
        self.number = list()

    def AddMemmber(self,name,number):	# 添加数据
        self.name.append(name)
        self.number.append(number)

    def __iter__(self):
        return self

    def __next__(self):
        if len(self.name) > self.g_number:
            name = self.name[self.g_number]
            number = self.number[self.g_number]
            self.g_number += 1
            return "姓名:"+name+", "+"学号:"+str(number)
        else:
            raise StopIteration

def main():
    test = IteratorClass()
    test.AddMemmber("tomato",2020)
    test.AddMemmber("potato",2021)
    test.AddMemmber("konato",2022)
    for member in test:
        print(member)

if __name__ == '__main__':
    main()

运行上段代码,结果如以下图示。
在这里插入图片描述
主线程执行顺序:

  1. 定义一个迭代器类IteratorClass,实例化一个对象test
  2. 使用AddMemmber函数,将个人信息加入库中
  3. 执行迭代运算,从test对象中取出每个人的个人信息
  4. 在迭代运算中(即for循环),迭代器对象会自动调用类中的iter函数,iter函数的返回值是一个迭代器。在此代码中,test对象的iter函数的返回值为自身,因为test对象自身就是一个迭代器对象
  5. 调用迭代器的next函数来取值,一次迭代调用一次next函数。
  6. Python中的迭代器协议就是每次调用next函数的对象会前进到下一个结果,
    而在迭代器中的值取完时则会抛出StopIteration异常

2. 生成器

生成器是一种特殊的迭代器。
例:

列表生成式: [ x*2 for x in range()10 ]
列表生成器: ( x*2 for x in range()10 )

2.1 yield

在函数定义时,若函数体中存在关键字yield,
那么该函数就是一个生成器模板
调用该函数,就是创建一个生成器对象
yield后面是谁,就把谁return,再次调用时从上次yield的地方继续执行。
最后,我们用代码来实现一下黄体字的编程逻辑:

g_number = 10		# 定义一个全局变量g_number

def generator():	# 定义一个生成器模板
    global g_number
    while True:
        print("----- 1 -----")
        print("当前number的值为:",g_number)
        yield g_number
        g_number -= 1
        print("当前number的值为:",g_number)
        print("----- 2 -----")

def main():
    test = generator()
    next(test)

if __name__ == '__main__':
    main()

因为迭代器都能通过调用next()函数使其运行,
生成器是一种特殊的迭代器,
所以这里的生成器对象test同样调用next函数来运行。
运行上述代码,结果如以下图示:
在这里插入图片描述
当我们修改main函数,将next函数运行两次,这时得到的结果如以下图示:

def main():
    test = generator()
    next(test)
    next(test)

在这里插入图片描述
由此,我们可以看出在函数定义中,
yield后面是谁,就把谁return,再次调用时从上次yield的地方继续执行,
当再次运行到yield时,再次将yield后面的值return。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章