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异常,来终止循环。

 l1 = ["hello","world",1,2]

 #for循环调用可迭代对象的__next__方法去取值,而且for循环会捕捉StopIteration异常,以终止对象
for i in l1:
print(i) aa = l1.__iter__() #等同于内置函数aa = iter(l1) 创建了一个list_iterator 列表迭代器
print(type(aa))
print(next(aa)) #内置函数 next()查看第一次迭代器的值
print(aa.__next__()) #迭代器本身对象的方法,第二次迭代器的值 跟 内置函数方法都是一样的
print(next(aa))
print(next(aa))
print(next(aa)) #没有可迭代的值了也就是迭代完了,会报错:StopIteration #迭代器迭代完,就不能再次迭代该迭代器 比如for 循环
for i in aa:
print(i)

demo

 # 首先获得Iterator对象:
it = iter([1, 2, 3, 4, 5]) #创建一个迭代器
# 循环:
while True:
try:
# 获得下一个值:
x = next(it)
print(x)
except StopIteration:
# 遇到StopIteration就退出循环
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.这个生成器内存空间的问题。

3.时间效率问题。

生成器是一个惰性的,根据惰性求值:也就是需要一个对象给一个对象

 

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

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

 #三元表达式格式

 res=值1  if  条件  else  值2 

 #如果条件满足 res 等于 值1  条件不满足就等于 值2
# demo 1
name = "xixi"
res = "xixi" if name == "xixi" else "hello"
print(res) #demo 2
num = 2 if False else 0
print(num)

2.列表生成式

 #列表生成式通过计算生成一个列表

 lis_gen = [ i for i in range(1,10)]  #列表生成式
print(lis_gen) lis1_gen = [i for i in range(1,10) if i%2 == 0] #生成一个偶数的列表
print(lis1_gen) lis2_gen = [ i * i for i in range(1,10) if i%2 == 1] #生成以个奇数乘自已本身奇数的列表
print(lis2_gen)

列表生成式[] demo

3.生成器表达式

 gen_exp = (i for i in range(10))  #生成器表达式
print(gen_exp) #generator
# for i in gen_exp: #取出生成器表达式的值,for循环
# print(i)
print(gen_exp.__next__()) #next方法
print(gen_exp.__next__())
print(gen_exp.__next__())
print(gen_exp.__next__())
print(gen_exp.__next__())

生成器表达式 () demo

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

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

总结:

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

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

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

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

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

1.2.2生成器函数

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

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

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

普通生成器:

 >>> gen = (i for i in range(5))
>>> gen
<generator object <genexpr> at 0x0000004DE29A70A0>
>>> next(gen)
0
>>> next(gen)
1
>>> next(gen)
2
>>> next(gen)
3
>>> next(gen)
4
>>> next(gen)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration

算法 实现生成器

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

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

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

for generator

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

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

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

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

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

 def fib1(number):
n,a,b = 0,0,1
while n<number:
yield b
a,b = b,a+b
n += 1
return "done"
aa = fib1(6)
print(aa) #generator
# print(aa.__next__())
for i in aa:
print(i)

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

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

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

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

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

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

生产 ,卖的过程

 #单线程一边发送,一边执行
import time
def consumer(name):
print("%s 准备吃包子啦!" %name)
while True:
baozi = yield print("包子[%s]来了,被[%s]吃了!" %(baozi,name))
def producer(name):
c = consumer('A')
c2 = consumer('B')
c.__next__()
c2.__next__()
print("老子开始准备做包子啦!")
for i in range(10):
time.sleep(1)
print("做了2个包子!")
c.send(i) #发送的值,就是yield的返回值
c2.send(i)
producer("xixi")

yield生成器,单线程并发

1.2.3生成器函数总结

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

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

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

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

  1. python基础之协程,列表生成式,生成器表达式

    三元表达式 #三元表达式 name = 'alex' name = 'egon' res='SB' if name == 'alex'else 'shuai' print(res)#输出:shuai ...

  2. Python入门基础之迭代和列表生成式

    什么是迭代 在Python中,如果给定一个list或tuple,我们可以通过for循环来遍历这个list或tuple,这种遍历我们成为迭代(Iteration). 在Python中,迭代是通过 for ...

  3. Python 非空即真、列表生成式、三元表达式 day3

    一.非空即真: Python程序语言指定任何非0和非空(null)值为true,0 或者 null为false 布尔型,False表示False,其他为True 整数和浮点数,0表示False,其他为 ...

  4. python基础--切片、迭代、列表生成式

    原文地址:https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/00143175684 ...

  5. Python开发的入门教程(九)-列表生成式

    介绍 本文主要介绍Python中列表生成式的基本知识和使用 生成列表 要生成list [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],我们可以用range(1, 11): >&g ...

  6. Python笔记(九)_切片、列表生成式

    切片 mylist[:3] 取前3位元素,0可省略不写 mylist[-4:] 取后4位元素,0可省略不写 mylist[2:4] 从第2个开始取,取到第4个,但第4个不取,取的元素值为4-2=2 m ...

  7. Python 高级特性(3)- 列表生成式

    range() 函数 日常工作中,range() 应该非常熟悉了,它可以生成一个迭代对象,然后可以使用 list() 将它转成一个 list # 判断是不是迭代对象 print(isinstance( ...

  8. xpinyin-函数返回多个值-lambda匿名函数-列表生成式-三元表达式

    import xpinyinp=xpinyin.Pinyin() #实例化print(p.get_pinyin('小白','')) 函数返回多个值:1.函数如果返回多个值的话,它会把这几个值放到一个元 ...

  9. python高级特性:切片/迭代/列表生成式/生成器

    廖雪峰老师的教程上学来的,地址:python高级特性 下面以几个具体示例演示用法: 一.切片 1.1 利用切片实现trim def trim(s): while s[:1] == " &qu ...

  10. Python 速通爆肝、列表推导式、生成器、装饰器、生命游戏

    列表推导式.赋值.切片(替换.插入).字符串处理与判断.enumerate().格式化字符串.读写文件.global 关键字.字符串startswith().类与对象.生成器.装饰器.Self.*ar ...

随机推荐

  1. mysql_建立索引的优缺点 #转自Starzm#

    建立索引的优缺点: 为什么要创建索引呢? 这是因为,创建索引可以大大提高系统的性能.         第一.通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性.         第二.可以大大加 ...

  2. sql server 里面的 dynamic Data Masking

    有时候啊,当我们存放在数据库里面的数据,需要明文存放,但是对于前台查询出来的,又不太希望明文放出去的时候(比方说客户的手机啊,邮箱啊)之类有点敏感的信息,之前通常是保存个明文,然后在前台展现的时候再特 ...

  3. Markdown:让书写更美好

    http://www.jianshu.com/p/17fdcf17bbb4 http://sdutlinux.org/t/218   文档整体解决方案 在自己的服务器上安装GitBook markdo ...

  4. eclipse svn账号更换

    在eclipse下用 svn的时候,我们习惯将用户名和密码保存.前天公司将svn的账号全部更换了,这时原来的eclipse保存的svn账号密码就失效了.那怎么样才能切换账号了,eclipse svn插 ...

  5. 如何用python在Windows系统下,生成UNIX格式文件

    平时测试工作中,少不了制造测试数据.最近一个项目,我就需要制造一批可在UNIX下正确读取的文件.为确保这批文件能从FTP下载成功,开发叮嘱我:“文件中凡是遇到换行,换行符必须是UNIX下的LF,而不是 ...

  6. CentOS安装MySQL

    好记性不如烂笔头,记录一下 yum list installed | grep mysql #检查是否安装了mysql yum -y remove mysql-libs.x86_64 #卸载已经安装的 ...

  7. 第3章 Linux常用命令(6)_关机重启命令

    8. 关机重启命令 8.1 关机重启命令 (1)shutdown [选项] 时间     ①选项 -c:取消前一个关机命令 -h:关机 -r:重启 ②应用举例:#shutdown –h now.shu ...

  8. java 异常

    1.java异常 2.自定义抛出 3.运行时异常,程序有问题,让使用者可以改' ' 4.return  和  throw的区别 return 符合函数要求的值    throw  有问题的时候用它结束 ...

  9. webpack中字体配置,可以引入bootstrap

    {test:/\.(eot|ttf|woff|woff2|svg)$/,loader:'file?name=fonts/[name].[ext]'} 将css中用到的字体全部提取存放到fonts目录下 ...

  10. 为普通Object添加类似AttachedProperty的属性

    为普通Object添加类似AttachedProperty的属性   周银辉 我们知道,在WPF中对应一个DependencyObject,我们很容易通过AttachedProperty来为类型附加一 ...