python 迭代对象 迭代器 生成器


迭代对象,迭代器,生成器

  • 若对象中实现了 __getitem__ 或者 __iter__ 方法,那么这个对象就是可迭代对象

  • 若对象中实现了** __next____iter__ 方法**,那么这个对象就是迭代器

  • 可迭代对象的背后其实是迭代器在起作用

使用了 yield 的函数被称为生成器(generator)

yield 是一个关键字,用于定义生成器函数,生成器函数是一种特殊的函数,可以在迭代过程中逐步产生值,而不是一次性返回所有结果。生成器是一个返回迭代器的函数,只能用于迭代操作,更简单点理解生成器就是一个迭代器。

当在生成器函数中使用 yield 语句时,函数的执行将会暂停,并将 yield 后面的表达式作为当前迭代的值返回。

然后,每次调用生成器的 next() 方法或使用 for 循环进行迭代时,函数会从上次暂停的地方继续执行,直到再次遇到 yield 语句。这样,生成器函数可以逐步产生值,而不需要一次性计算并返回所有结果。

调用一个生成器函数,返回的是一个迭代器对象。可以说所有生成器对象都是迭代器对象,有一点细微的区别:

  • 生成器对象更倾向于在无限中集合中惰性的输出需要的数据
  • 迭代器更倾向于在实现已知道所有数据的情况下惰性输出需要的数据

恰当的例子就是斐波那契数列,可以用生成器实现一个斐波那契数列,但因为该数列的元素是无限多个,所以说其是迭代器实现的就没有说由生成器实现的说法恰当。

判断对象是否是可迭代对象的方法

方法一:

print('__iter__' in dir([1, 2, 3]))  # True

方法二:

from collections.abc import Iterable

print(isinstance('123', Iterable))  # True
arr = [1, 2, 3]
arr_iter = arr.__iter__()
print(arr_iter.__next__())  # 1

# arr是可迭代对象, 不是迭代器 
print('__next__' in dir(arr))  # False

# arr_iter是迭代器
print('__next__' in dir(arr_iter))  # True

1. __iter__()

该方法返回的是当前对象的迭代器类的实例。因为可迭代对象与迭代器都要实现这个方法,因此有以下两种写法。

  1. 用于可迭代对象类的写法,返回该可迭代对象的迭代器类的实例。
  2. 用于迭代器类的写法,直接返回self(即自己本身),表示自身即是自己的迭代器。

2. __next__ ()

返回迭代的每一步,实现该方法时注意要最后超出边界要抛出StopIteration异常。

    def __init__(self, start, end):
        self.start = start
        self.end = end

    def __iter__(self):
        return self

    def __next__(self):
        if self.start < self.end:
            self.start += 1
            return self.start - 1
        else:
            raise StopIteration


for i in MyRange(1, 3):
    print(i)  # 1 2
for i in range(1, 3):
    print(i)  # 1 2

3. iter(source, sentinel=None)

def iter(source, sentinel=None): # known special case of iter
    """
    iter(iterable) -> iterator
    iter(callable, sentinel) -> iterator
    
    Get an iterator from an object.  In the first form, the argument must
    supply its own iterator, or be a sequence.
    In the second form, the callable is called until it returns the sentinel.
    """
    pass

Example 1:

it = iter([1, 2, 3, 4, 5])

def func():
    return next(it)

for j in iter(func, 4):
    print(j)
# 1
# 2
# 3

Example 2:

class Next:
    def __init__(self):
        self.data = [0, 1, 2, 3, 4]
        self._iter = iter(self.data)

    def get_len(self):
        return len(self.data)

    def __iter__(self):
        print('iter')
        return self

    def __call__(self):
        print("call")
        return next(self._iter)

    def __next__(self):
        print('i am next')
        return next(self._iter)

这里Next()是初始化创建一个实例,该实例可以被调用,也就是Next()()时会调用Next().__call__()

iter对象的第一个参数如果是可调用对象时,会一直调用该对象直到与第二个参数相同或者**raise StopIteration**

而每次执行__call__时,会对self._iter迭代一次。这里__next____iter__没有执行。

for it in iter(Next(), 6):
    print(it)

# call
# 0
# call
# 1
# call
# 2
# call
# 3
# call
# 4
# call
iter_next = iter(Next())
print("===================")
for it in iter_next:
    print(it)

# iter
# ===================
# iter
# i am next
# 0
# i am next
# 1
# i am next
# 2
# i am next
# 3
# i am next
# 4
# i am next
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值