python迭代器和生成器(3元运算,列表生成式,生成器表达式,生成器函数)

1.1迭代器

什么是迭代器:

迭代器是一个可以记住遍历的位置对象

迭代器对象从集合的第一个元素元素开始访问,直到所有元素被访问完结束,迭代器只能往前不会后退。

迭代器有两个基本方法:iter ,next 方法

内置函数iter(),next()  本质上都是用的对象.__iter__(),__next__()的方法

内置函数 iter(iterable),表示把可迭代对象 变成迭代器(iterator)

内置函数next(iterator) ,表示查看下一次迭代的值(当然也可以用 iterator.__next__() ,查看下一次迭代的值)

1.1.2迭代器协议

1.迭代器(iterator)协议是指:对象必须提供一共next方法,执行该方法妖魔返回迭代中的下一项,要么就引起一个Stopiteration异常,已终止迭代。

2.可迭代对象:实现了迭代器协议的对象,(该对象内部定义了一个__iter__()的方法  例:str.__iter__())就是可迭代对象

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

1.1.3python中的for循环

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

(字符串,列表,元祖,字典,集合,文件对象),这些都不是可迭代对象,只不过在for循环,调用了他们内部的__iter__方法,把他们变成了可迭代对象。然后for循环调用可迭代对象的__next__方法去去找,然后for循环会自动捕捉StopIteration异常,来终止循环。

 1 l1 = ["hello","world",1,2]
 2
 3 #for循环调用可迭代对象的__next__方法去取值,而且for循环会捕捉StopIteration异常,以终止对象
 4 for i in l1:
 5     print(i)
 6
 7 aa = l1.__iter__()  #等同于内置函数aa = iter(l1) 创建了一个list_iterator 列表迭代器
 8 print(type(aa))
 9 print(next(aa))   #内置函数 next()查看第一次迭代器的值
10 print(aa.__next__())   #迭代器本身对象的方法,第二次迭代器的值   跟 内置函数方法都是一样的
11 print(next(aa))
12 print(next(aa))
13 print(next(aa))  #没有可迭代的值了也就是迭代完了,会报错:StopIteration
14
15
16 #迭代器迭代完,就不能再次迭代该迭代器 比如for 循环
17 for i in aa:
18     print(i)

demo

 1 # 首先获得Iterator对象:
 2 it = iter([1, 2, 3, 4, 5]) #创建一个迭代器
 3 # 循环:
 4 while True:
 5     try:
 6         # 获得下一个值:
 7         x = next(it)
 8         print(x)
 9     except StopIteration:
10         # 遇到StopIteration就退出循环
11         break

demo2 :循环比迭代器更强大

总结:

1.可作用于for循环对象本身都是iterable(可迭代对象)类型,或者对象本身有obj.__iter__方法也是iterable

2.凡是可作用于next()函数的对象本身itertor(迭代器)类型,或者obj.__next__也是iterator ,迭代器是一个惰性序列

因为需要调用next,才会获得元素,迭代完,就不能再次迭代。

3.list、dict、str等是iterable,但不是iterator不过可以通过iter()函数获得一个迭代器对象。

1.2生成器

什么是生成器?

1.从字面理解是不是:生成一个容器

2.在python中,一边循环,一边计算的机制,称为生成器(generator)。

3.可以理解为一种数据类型,这种类型自动实现了迭代器协议。(其他的数据类型需要调用自已的内置__iter__方法或则iter()的内置函数),所以生成器就是一个可迭代对象。

生成器分类以及在python中的表现形式。(python有两种不同的方式提供生成器)

1.生成器函数:常规函数定义,但是,使用yield语句而不是return语句的返回结果。yield语句一次返回一个结果,在每个结果中间,保留函数的状态,以便再上一次状态的重新执行。

2.生成器表达式:类似于列表推导,但是生成器返回按需产生结果的一种对象,而不是一次构建一个结果列表

为何使用生成器,生成器的优点:

python使用生成器对延迟操作提供了支持。所谓延迟操作,是指需要的时候才产生结果,而不是立即生成结果

这就是生成器的好处

生成器小结:

1.生成器是可迭代对象

2.实现了延迟计算,看内存(按需,执行)

3.生成器本质和其他类型一样,都是实现了迭代器协议,只不过生成器是一边计算,一边生成,从而节省内存空间,

其余的可迭代对象可没有好处。

1.2.1生成器表达式、列表生成式、三元表达式

1.三元运算或则3元表达式

 1 #三元表达式格式
 2
 3 res=值1  if  条件  else  值2
 4
 5 #如果条件满足 res 等于 值1  条件不满足就等于 值2
 6 # demo 1
 7 name = "xixi"
 8 res = "xixi"  if name == "xixi" else "hello"
 9 print(res)
10
11 #demo 2
12 num = 2 if False else 0
13 print(num)

2.列表生成式

 1 #列表生成式通过计算生成一个列表
 2
 3 lis_gen = [ i for i in range(1,10)]  #列表生成式
 4 print(lis_gen)
 5
 6 lis1_gen = [i for i in range(1,10) if i%2 == 0]  #生成一个偶数的列表
 7 print(lis1_gen)
 8
 9 lis2_gen = [ i * i for  i in range(1,10) if i%2 == 1]  #生成以个奇数乘自已本身奇数的列表
10 print(lis2_gen)

列表生成式[] demo

3.生成器表达式

1 gen_exp = (i for i in range(10))  #生成器表达式
2 print(gen_exp) #generator
3 # for i in gen_exp:  #取出生成器表达式的值,for循环
4 #     print(i)
5 print(gen_exp.__next__()) #next方法
6 print(gen_exp.__next__())
7 print(gen_exp.__next__())
8 print(gen_exp.__next__())
9 print(gen_exp.__next__())

生成器表达式 () demo

1 gen = (i for i in range(10**100))  #生成器表达式
2 lis = [i for i in range(10**100)]  #列表生成式
3
4 #生成器,更省内存,需要一个取一个
5 print(gen.__next__())
6 print(lis)  #需要在内存空间创建1-10**100序列

生成器表达式和列表生成式比较 ()和[]

总结:

1.把列表解析的[]换成()得到就是生成器表达式

2.列表生成式式一个构建一个结果列表,生成器表达式:是返回按需产生结果的一个对象

3.列表解析与生成器表达式都是一种便利的编程方式,只不过生成器表达式更节省内存

4.python不但使用迭代器协议让for循环更加通用,大部分内置函数,也是使用迭代器协议访问对象的

如,sum函数是python的内置函数,该函数使用迭代器协议访问对象,而生成器实现了迭代器协议

1.2.2生成器函数

在python中,使用了yield的函数就称为生成器(generator)

1.跟普通函数不同的是,生成器是一个返回迭代器的函数,只能用于迭代操作,可以理解为:生成器就是一个迭代器

2.在调用生成器运行过程中,每次遇到yield是函数会暂停并保存当前所有的运行信息,返回yield值。并在下一次执行next方法时,从当前位置继续运行。

普通生成器:

 1 >>> gen = (i for i in range(5))
 2 >>> gen
 3 <generator object <genexpr> at 0x0000004DE29A70A0>
 4 >>> next(gen)
 5 0
 6 >>> next(gen)
 7 1
 8 >>> next(gen)
 9 2
10 >>> next(gen)
11 3
12 >>> next(gen)
13 4
14 >>> next(gen)
15 Traceback (most recent call last):
16   File "<stdin>", line 1, in <module>
17 StopIteration

算法 实现生成器

注:generator保存的是算法,每次调用next方法,就计算出gen的下一个元素的值,直到计算到最后一个元素,没有更多元素时,就StopIteration的错误。

当然,上面这种不断调用next(gen),用着有点坑,正确的方法是使用for循环,因为generator也是iterator;

1 >>> g = (i for i in range(5))
2 >>> for i in g:
3 ...     print(i)
4 ...
5 0
6 1
7 2
8 3
9 4

for generator

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

generator非常强大,如果计算的算法比较复杂,用for循环无法实现的时候,还可以用函数来实现。

例:斐波拉契数列 后面的一个数等于前面两个数相加的和

1 def fib(number):
2     #得出几个斐波拉契数列
3     count,a,b = 0,0,1
4     while count < number:
5         print(b)
6         a,b = b,a+b
7         count += 1
8     return "done"
9 fib(5)

斐波拉契数列,普通函数定义

 1 def fib1(number):
 2     n,a,b = 0,0,1
 3     while n<number:
 4         yield b
 5         a,b = b,a+b
 6         n += 1
 7     return "done"
 8 aa = fib1(6)
 9 print(aa)  #generator
10 # print(aa.__next__())
11 for i in aa:
12     print(i)

斐波拉契数列,yield函数 定义

注:如果一个函数定义中包含yield关键字,那么这个函数就不是普通函数,而是一个generator

注:generator和函数执行的流程不一样,

函数是顺序执行,遇到return语句或则最后一行函数函数语句就返回。

而变成generator的函数,在每次调用next()的时候执行,遇到yield语句返回,再次执行从上次返回的yield语句处继续执行

 1 def packet():
 2     for i in range(1,10):
 3         print("开始生产包子")
 4         yield  "第 %d 屉包子" %(i)
 5         print("卖包子,买完再生产")
 6 cs = packet()  #生成一个做包子的生成器,相当于做包子的
 7 # print(cs)
 8 q = print(cs.__next__()) #卖包子的
 9 print(cs.__next__())
10 for i in cs:
11     print(i)

生产 ,卖的过程

 1 #单线程一边发送,一边执行
 2 import time
 3 def consumer(name):
 4     print("%s 准备吃包子啦!" %name)
 5     while True:
 6        baozi = yield
 7
 8        print("包子[%s]来了,被[%s]吃了!" %(baozi,name))
 9 def producer(name):
10     c = consumer(‘A‘)
11     c2 = consumer(‘B‘)
12     c.__next__()
13     c2.__next__()
14     print("老子开始准备做包子啦!")
15     for i in range(10):
16         time.sleep(1)
17         print("做了2个包子!")
18         c.send(i) #发送的值,就是yield的返回值
19         c2.send(i)
20 producer("xixi")

yield生成器,单线程并发

1.2.3生成器函数总结

1.生成器函数语法上和普通函数类似:生成器使用yield语句返回一个值,而常规函数使用return语句返回一个值

2.生成器自动实现迭代器协议,迭代完,就不能再次迭代。

3.状态挂起:生成器使用yield语句返回一个值。挂起该生成器函数的状态。

时间: 2024-10-25 17:06:14

python迭代器和生成器(3元运算,列表生成式,生成器表达式,生成器函数)的相关文章

python_day04 函数嵌套 名称空间和作用域 闭包 装饰器 迭代器 生成器 列表解析 三元表达式 生成器表达式

本节课重要知识点内容如下: 函数嵌套 名称空间和作用域 闭包 装饰器 迭代器 生成器 列表解析 三元表达式 生成器表达式 1.函数嵌套 函数的嵌套调用:在调用一个函数的过程中,又调用了其他函数函数的嵌套定义:在一个函数的内部,又定义另外一个函数 def bar(): print('from nbar')def foo(): print('from foo') bar()foo()def max2(x,y): if x > y: return x else: return ydef max4(a,

Python学习笔记(四) 列表生成式_生成器

笔记摘抄来自:https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/0014317799226173f45ce40636141b6abc8424e12b5fb27000 本文章仅供自己复习使用,侵删: 列表生成器 # 例如,列出当前目录下的所有文件和目录名,可以通过一行代码实现: import os [d for d in os.listdir('.')] #for循环后面还可以加上

Python学习笔记__3.3章 列表生成式

# 这是学习廖雪峰老师python教程的学习笔记 1.概览 列表生成式即List Comprehensions,是Python内置的非常简单却强大的可以用来创建list的生成式 1.生成list [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] list(range(1, 11)) 2.列表生成式 [1x1, 2x2, 3x3, ..., 10x10] [x*x for x in range(1,11)] 3.使用两层循环 >>>[m + n for m in 'ABC'

python入门第十六天__列表生成式

列表生成式即List Comprehensions,是Python内置的非常简单却强大的可以用来创建list的生成式. 举个例子,要生成list [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]可以用list(range(1, 11)): >>> list(range(1, 11)) [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 但如果要生成[1x1, 2x2, 3x3, ..., 10x10]怎么做?方法一是循环: >>> L = []

python的一些高级特性(列表生成式)

列表生成式 如果要生成[1x1, 2x2, 3x3, ..., 10x10]怎么做? >>> [x * x for x in range(1, 11)] [1, 4, 9, 16, 25, 36, 49, 64, 81, 100] for循环后面还可以加上if判断,这样我们就可以筛选出仅偶数的平方: >>> [x * x for x in range(1, 11) if x % 2 == 0] [4, 16, 36, 64, 100] 还可以使用两层循环,可以生成全排列

列表生成式&amp;三元表达式

列表生成式: 用于生成一个新的列表,是Python内置的一种极其强大的生成list的表达式.一.语法格式:[exp for iter_var in iterable] 工作过程: (1)迭代iterable中的每个元素: (2)每次迭代都先把结果赋值给iter_var,然后通过exp得到一个新的计算值: (3)最后把所有通过exp得到的计算值以一个新列表的形式返回. 例如: L=[i for i in range(10)] print(L)#[0, 1, 2, 3, 4, 5, 6, 7, 8,

列表生成式、生成器&amp;迭代器

一.列表生成式 先有列表[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],要求你把列表里的每个值加1,怎么实现? 方法一: a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] b = [] for i in a:b.append(i+1) a = b print(a) 此方法内存中会同时有两份列表,因此不适合处理大规模数据. 方法二: a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] for index,i in enumerate(a): a[

python迭代器,生成器,列表生产式

目录 列表生成式 生成器 1.定义 2.作用 3.返回值 迭代器 1.特点 2.常见的迭代器 3.可迭代对象 列表生成式 列表生成式即List Comprehensions,是Python内置的非常简单却强大的可以用来创建list的生成式. 例如: >>> [x * x for x in range(1, 11)] [1, 4, 9, 16, 25, 36, 49, 64, 81, 100] 生成器 1.定义 一个函数调用时返回一个迭代器,那这个函数就叫做生成器(generator),如

Python函数编程——列表生成式和生成器

Python函数编程--列表生成式和生成器 一.列表生成式 现在有个需求,现有列表a=[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],要求你把列表里的每个值加1,你怎么实现? 1.二逼青年版 生成一个新列表b,遍历列表a,把每个值加1后存在b里,最后再把a=b, 这样二逼的原因不言而喻,生成了新列表,浪费了内存空间. >>> a [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> b = [] >>> for i in