python中迭代器和生成器_python 中的迭代器和生成器详解

迭代器

学习过python的童鞋都应该知道python中有三大神器,即 迭代器、生成器和装饰器,所谓神器,必有其神奇之处,今天和大家一起学习一下迭代器和生成器。

迭代是python比较强大的功能之一,说起迭代,我们可能会想到,对于一个列表list,一个元组tuple,访问的时候都可以使用 for .. in .. ,没错,这就是迭代,它是访问集合元素的一种方式,在从头到尾遍历可迭代对象时,能够记住遍历的位置。

这里给大家区分两个概念 可迭代对象(iterable)和迭代器(iterator), 我们往往说某个对象是不是可迭代的,而迭代器可以抽象为一个‘器’,就是在从头到尾遍历可迭代对象中的某一元素时,能够记住遍历的位置的那玩意儿,二者之间有本质区别,下面举例说明一下

from collections import Iterable

test = ['a', 'b']

for i in test:

print(i)

# 输出结果,说明列表是可迭代的

a

b

isinstance([], Iterable)

True

for i in 10:

print(i)

#输出结果,说明整型数字是不可迭代的

TypeError: 'int' object is not iterable

isinstance(10, Iterable)

False

上面我们看到的是可迭代对象的外在表现,那么可迭代对象的本质又是什么呢?答案就是一个具备__iter__方法的对象就是可迭代对象,话不多说,上代码看一下

from collections import Iterable

class MyIter():

def __init__(self):

pass

def __iter__(self):

pass

if __name__ == "__main__":

test = MyIter()

print(isinstance(test, Iterable))

输出结果

True

上面说过迭代器能够记住可迭代对象属性的位置,其本质是在可迭代对象中加了__next__()方法(python2中是next()方法),下面手动实现一个迭代器:

class MyIterator():

def __init__(self):

self.test_list = ['Hello', 'I', 'Love', 'python']

self.position = 0

def __iter__(self):

# 要返回一个迭代器,这里返回自身

return self

def __next__(self):

# 该方法的主要作用记录迭代输出位置

if self.position < len(self.test_list):

ret = self.test_list[self.position]

self.position += 1

return ret

# 当超出列表长度的时候,抛出停止迭代的异常

else:

raise StopIteration

if __name__ == "__main__":

test = MyIterator()

for i in test:

print(i, end=' ')

# 输出结果

Hello I Love python

总结一下,判断一个对象是不是可迭代的,就看该对象有没有实现__iter__()方法,要判断一个对象是不是迭代器,就看该对象有没有实现__iter__()方法和__next__()方法。我们平时用的比较多的for .. in ..循环,其执行过程的本质就是通过__iter__()获取一个可迭代对象,然后通过该调用对象的__next__()方法获取下一个值,知道满足停止迭代的条件之后,抛出停止迭代的异常,然后停止循环。

生成器

生成器(generator)是一种的特殊的迭代器,其特殊之处在于我们可以根据需要生成数据,生成器的创建方式有两种,第一种比较简单,将列表推导式的[]换成()就是生成器.

In [3]: a = [x**2 for x in range(5)]

In [4]: a

Out[4]: [0, 1, 4, 9, 16]

In [5]: b = (x**2 for x in range(5))

In [6]: b # b是一个生成器对象

Out[6]: at 0x000001E45FF01B88>

# 生成器具有__next__()方法

In [7]: b.__next__()

Out[7]: 0

In [8]: b.__next__()

Out[8]: 1

第二种方式就是通过使用yield创建生成器,一个函数,只要里面含有yield,那么它一定就是生成器,下面写个简单的代码说明一下通过yield创建的生成器。

def my_generator():

i = 0

print("1111111")

while i<5:

yield i

i += 1

print("22222")

print("33333")

if __name__ == "__main__":

gg = my_generator()

print(gg)

# 输出

print(gg.__next__())

# 1111111

# 0

print(gg.__next__())

# 22222

# 1

print(gg.__next__())

# 22222

# 2

简述一下上面代码执行的流程:函数执行到第一步(gg=my_generator())的时候,python编译器发现函数中有yield,将这个函数定义为一个生成器,于是实例化gg为一个生成器对象,上面说过,生成器是一个特殊的迭代器,通过第一次调用__next__()方法,函数从上往下执行,当执行到yield的时候,将yield 后的对象(0)返回,当第二次调用__next__()方法的时候,会接着yield i继续往下执行,所以先打印22222,执行到yield的时候,将yield 后的对象(1)返回,以此类推。

讲到yield,总避免不了一个话题,那就是yield与return的对比,二者都能结束函数的运行,他们的区别主要是return 之后,函数下次执行只能从头开始执行,而yield 能够接着继续执行,这就是二者主要区别。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值