Python迭代器,生成器,可迭代对象详解

目录

1.迭代器

2.生成器

yield关键字

3.可迭代对象

range功能

常见的数据类型

4.判断是迭代器or可迭代对象



1.迭代器

迭代器的类型定义:

1.当类中定义了__iter__和__next__两个方法;

2.__iter__方法需要返回对象本身,即:self

3.__next__方法,返回下一个数据,如果没有数据了,则需要抛出一个StopIteration的异常。

官方文档:https://docs.python.org/3/library/stdtypes.html#iterator-types

下面我们来详解一下:

# 创建迭代器类型:
class myfunc(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

首先我们创建了一个名为myfunc的类,他继承自基类object,(object是所有类的基类,它是所有内置类型的父类,包括整数、字符串、列表等等。myfunc通过继承object类,可以创建一个普通的Python类,可以使用一些通用的魔术方法,如__iter____next__。这样就可以创建一个迭代器对象,并实现自定义的迭代逻辑。

然后我们根据实例化创建一个迭代器对象并调用__next__方法:

# 根据类实例化创建一个迭代器对象
A = myfunc()

c1 = A.__next__()
c2 = A.__next__()
c3 = A.__next__()  # 抛出异常

# 或者通过以下方式执行
c1 = next(A)
c2 = next(A)
c3 = next(A)  # 抛出异常

 我们也可以通过for循环进行打印输出:

c = myfunc()
for i in c:
    print(i,end = " ")

# 结果输出 1 2

首先执行迭代器的对象的__iter__方法并获取返回值,把c这个实例对象传入给__iter__的self,又返回自己。他会一直反复地执行next(对象)。

2.生成器

定义:yiled为关键字,当yield出现在函数中,代表他为生成器函数,生成器函数后一加括号就是生成器对象。

以下是一个简单的实例: 

# 创建生成器函数
def func():
    yield 1
    yield 2


# 创建生成器对象(内部是根据生成器类generator创建的对象,生成器内部也声明了:__iter__,__next__方法)
obj1 = func()

因为生成器内部也定义了__iter__与__next__,并且完全符合迭代器的定义规则,所以:

生成器是一种特殊的迭代器

他也可以通过 next取值,没有值也会抛出异常,也可使用for循环(这里不再举例展示)。

yield关键字

在Python中,yield是一个关键字,用于定义生成器函数。生成器函数是一种特殊的函数,它可以暂停执行并返回一个中间结果,然后再次从上次暂停的地方继续执行。

具体来说,当一个函数中包含了yield关键字时,它将返回一个生成器对象。生成器对象可以被迭代,每次迭代时会执行生成器函数中的代码,直到遇到yield语句。yield语句会将一个值返回给迭代器,并将函数的当前状态保存下来。下次迭代时,函数将从上次暂停的地方继续执行。

下面是一个简单的示例代码:

def generate_numbers(n):
    for i in range(n):
        yield i

# 使用生成器函数创建生成器对象
numbers = generate_numbers(5)

# 迭代生成器对象
for num in numbers:
    print(num,end=" ")


# 输出结果为:0 1 2 3 4
  • generate_numbers是一个生成器函数,它接受一个整数参数n
  • 在函数内部,使用for循环和yield语句生成从0到n-1的数字。
  • 当生成器函数被调用时,它不会立即执行,而是返回一个生成器对象。
  • for循环中,每次迭代会执行生成器函数中的代码,直到遇到yield语句。
  • yield语句将一个数字返回给迭代器,并且函数的当前状态被保存下来。
  • 下次迭代时,函数将从上次暂停的地方继续执行,生成下一个数字。

 通过生成器函数和yield语句,我们可以按需生成数据,而不是一次性生成所有数据,从而节省内存和提高效率。

3.可迭代对象

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

简单的例子:

class func(object):
    def __iter__(self):
        return self  # 返回可迭代对象或生成器对象


obj = func()  # obj 是可迭代对象

for i in obj:
    pass

可迭代对象是可以使用for来进行循环,在循环的内部其实是先执行__iter__方法,获取其迭代器对象,然后再在内部执行这个迭代器对象的next功能,逐步取值。实例说明:

# 创建迭代器类型:
class myfunc(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


class func(object):
    def __iter__(self):
        return myfunc()  # 获取myfunc迭代器对象


A = func()

for i in A:
    print(i,end=" ")  

#  输出:1 2

                     

在主程序中,我们创建了一个func的实例对象,并使用for循环迭代这个对象。由于func对象是可迭代的,它会调用__iter__方法,获取到一个myfunc迭代器对象。然后,在每次迭代中,myfunc对象会调用__next__方法,返回一个递增的计数器值,并打印输出。

range功能

讲到实例对象,我们会想到range,其实类似a= range(100)这样的返回的a是一个可迭代对象,怎么证明呢?我们可以打开终端:

可以看到,他只有__iter__方法,没有__next__对象,所以他是可迭代对象。

 而当执行a.__iter__并把它赋值给b,此时b就是一个迭代器对象,它自然就可以执行__next__方法了。

我们可以自定义range类:

class IterRange(object):
    def __init__(self, num):
        self.num = num
        self.counter = -1

    def __iter__(self):
        return self

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


class Xrange(object):
    def __init__(self, max_num):
        self.max_num = max_num

    def __iter__(self):
        return IterRange(self.max_num)


obj = Xrange(100)

for i in obj:
    print(i)

在主程序中,我们创建了一个Xrange对象,传入最大值为100。然后,使用for循环迭代这个对象。由于Xrange对象是可迭代的,它会调用__iter__方法,获取到一个IterRange迭代器对象。然后,在每次迭代中,IterRange对象会调用__next__方法,返回一个递增的计数器值,并打印输出。

因此,运行上述代码会输出从0到99的整数。

常见的数据类型

a = list([10,20,30,40])

a 也是一个可迭代对象,因为在列表中声明了一个__iter__方法并且返回一个迭代器对象

终端如图:

列表,元祖,字典,这些常见的数据类型创建的一个对象都是可迭代对象

4.判断是迭代器or可迭代对象

如果你不确定某个对象是否是可迭代对象,迭代器,可以用代码判断

from collections.abc import Iterable, Iterator # 导入方法

d = [11, 22, 33]
print(isinstance(d, Iterator))  # False,判断是否是迭代器,判断依据是__iter__和__next__

print(isinstance(d, Iterable))  # True ,判断是否迭代,判断依据是是否有__iter__且返回迭代器对象

d1 = d.__iter__()
print(isinstance(d1, Iterator))  # True
print(isinstance(d1, Iterable))  # True

如果只要判断一个对象是否是可迭代对象,结合两者使用

d = [11, 22, 33]
if isinstance(d, Iterable) and isinstance(d, Iterator):
    print("d是迭代器对象")
else:
    print("d是一个可迭代对象")

# 输出 “d是一个可迭代对象”

关于迭代器,生成器,可迭代对象就讲解到这里,后续可能会更新,谢谢各位的支持!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

One>twenty

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

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

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

打赏作者

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

抵扣说明:

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

余额充值