欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 编程语言 > python >内容正文

python

python的迭代器无法输出值_python迭代器和生成器

发布时间:2025/4/16 python 49 豆豆
生活随笔 收集整理的这篇文章主要介绍了 python的迭代器无法输出值_python迭代器和生成器 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

人生还早,谁能笑到最后呢,坚持吧!

1.迭代器协议

由于生成器自动实现了迭代器协议,我们有必要了解迭代器协议是什么,才能更好的理解生成器。

1)迭代器协议:对象要提供__next()__方法,它要么返回迭代中的下一个对象,要么引起一个StopIteration错误,终止迭代

2)可迭代对象:实现了迭代器协议的对象

3)协议是一种约定,可迭代对象实现了迭代器协议,python的内部工具(如for循环,sum,min,max函数等)使用迭代器协议访问对象。

for循环的本质:循环所有对象,全都是使用迭代器协议

(字符串,列表,元组,字典,集合,文件对象)这些都不是可迭代对象,只不过在for循环式,调用了他们内部的__iter__方法,把他们变成了可迭代对象

list = ['a','b',1,2]

# for i in list:

# print(i)

list_iter = list.__iter__()#调用__iter__方法将list对象变成可迭代对象

print(list_iter.__next__())依次调用,知道引起StopIteration错误

print(list_iter.__next__())

print(list_iter.__next__())

print(list_iter.__next__())

用while循环模拟for循环做的事情

list_iter = list.__iter__()

while True:

try:

print(list_iter.__next__())

except StopIteration:

print('迭代完毕,可以终止')

break

迭代器对象的本质是一种数据流,它只是一个有序的序列,我们不能提前知道它的长度,只有不断通过__next__()取出下一个值。

Interator甚至可以表示一个无限大的数据流,例如全体自然数。而使用list是永远不可能存储全体自然数的。

优点

1):迭代器提供了一种不依赖于索引的取值方式,这样就可以遍历那些没有索引的可迭代对象了(字典,集合,文件)

2):迭代器与列表比较,迭代器是惰性计算的,,只有在需要返回下一个数据时才计算,更节省内存

缺点:

1):无法获取迭代器的长度,使用不如列表索引取值灵活

2):一次性的,只能往后取值,不能倒着取值

如何查看一个对象是不是可迭代对象和迭代器对象

from collections import Iterable,Iterator#导入模块

list = ['a','b',1,2]

list_iter = list.__iter__()

#isinstance

print(isinstance(list,Iterable))#是否是可迭代对象

print(isinstance(list,Iterator))#是否是迭代器对象

print(isinstance(list_iter,Iterable))

print(isinstance(list_iter,Iterator))

小结:

凡是可作用于for循环的对象都是Iterable类型;

凡是可作用于next()函数的对象都是Iterator类型,它们表示一个惰性计算的序列,也就是说你需要取值时才给你取;

集合数据类型如list、dict、str等是Iterable但不是Iterator,不过可以通过iter()函数获得一个Iterator对象。

协程函数

如果在一个函数内部yield的使用方式是表达式形式的话,如x=yield,那么该函数称为协程函数,比线程更小

def eater(name):

food_list=[]

while True:

food=yield food_list

food_list.append(food)#因为有yied

e=eater('铁根') #一个生成器的内存地址

print(next(e)) #初始化迭代器

print(e.send('包子'))

print(e.send('韭菜馅包子'))

print(e.send('大蒜包子'))

2.生成器

通过列表生成式,我们可以创建一个列表。但是我们知道受内存的限制,我们的列表容量是有限的,而且创建包含100万个元素的列表,我们只用到前几个,剩下的都是浪费内存空间。

所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间。在Python中,这种一边循环一边计算的机制,称为生成器:generator。

要创建一个generator,有很多种方法。第一种方法很简单,只要把一个列表生成式的[]改成(),就创建了一个generator:

l=[x*x for x in range(10)]

print(l)

g=(x*x for x in range(10))

print(g)

打印结果

[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

at 0x0000000001E70F10>

取generator值用__next__()一个一个打印出来

print(g.__next__())

print(g.__next__())

print(g.__next__())

print(g.__next__())

print(g.__next__())

print(g.__next__())

0

1

4

9

16

25

generator也是可迭代对象,所以也可以使用for循环

for i in g:

print(i)

0

1

4

9

16

25

36

49

64

81

所以,我们创建了一个generator后,基本上永远不会调用next(),而是通过for循环来迭代它,并且不需要关心StopIteration的错误。

generator非常强大。如果推算的算法比较复杂,用类似列表生成式的for循环无法实现的时候,还可以用函数来实现。

比如,著名的斐波拉契数列(Fibonacci),除第一个和第二个数外,任意一个数都可由前两个数相加得到:

1, 1, 2, 3, 5, 8, 13, 21, 34, ...

斐波拉契数列用列表生成式写不出来,但是,用函数把它打印出来却很容易:

def fib(max):

n, a, b = 0, 0, 1

while n < max:

print(b)

a, b = b, a + b

n = n + 1

return 'done'

fib(20)

1

1

2

3

5

8

13

21

34

55

89

144

233

377

610

987

1597

2584

4181

6765

仔细观察,可以看出,fib函数实际上是定义了斐波拉契数列的推算规则,可以从第一个元素开始,推算出后续任意的元素,这种逻辑其实非常类似generator。

也就是说,上面的函数和generator仅一步之遥。要把fib函数变成generator,只需要把print(b)改为yield b就可以了:

def fib(max):

n, a, b = 0, 0, 1

while n < max:

yield b

a, b = b, a + b

n = n + 1

return 'done'

f = fib(6)

print(f)

这里,最难理解的就是generator和函数的执行流程不一样。函数是顺序执行,遇到return语句或者最后一行函数语句就返回。而变成generator的函数,在每次调用next()的时候执行,遇到yield语句返回,再次执行时从上次返回的yield语句处继续执行。

定义generator的另一种方法。如果一个函数定义中包含yield关键字,那么这个函数就不再是一个普通函数,而是一个generator

我们把函数变成generator后,基本上也不再使用__next__()方法,都是用for循环来迭代,但是用for循环调用generator时,发现拿不到generator的return语句的返回值。

def fib(max):

n, a, b = 0, 0, 1

while n < max:

# print(b)

yield b

a, b = b, a + b

n = n + 1

return 'done'

for i in fib(5):

print(i)

1

1

2

3

5

如果想要拿到返回值,必须捕获StopIteration错误,返回值包含在StopIteration的value中:

while True:

try:

x=next(g)

print(x)

except StopIteration as e:

print('Generator return value:',e.value)

break

2

3

5

Generator return value: done

看到一张图方便理解列表等容器,生成器,可迭代对象,迭代器之间的关系

小结:

generator可以是表达式也可以是函数,它保存的是算法,同时它是iterable对象,它也是一个generator。

总结

以上是生活随笔为你收集整理的python的迭代器无法输出值_python迭代器和生成器的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。