1.迭代器

  迭代就是一个更新换代的过程,每次迭代都必须基于上一次的结果。

  迭代器就是迭代取值的工具。举个例子:

while True:
print('循环输出')

  此代码会无限循环输出文字,是个死循环,并不是迭代,因为迭代是每次输出都与上一次输出有关,所以迭代应该是这样:

list1=[1,2,3,4,5]
n=0
while n<len(list1):
print(list1[n])
n+=1
#输出结果>>>1
#
#
#
#

  迭代也是有对象的,有的数据类型就不支持迭代

  可迭代:字符串,列表,元组,字典,集合,文件对象

  其中,字典被迭代后获取的是字典中的key值。

  为什么要使用迭代:迭代提供了不依赖索引取值的方法。如字典,集合等无序的数据类型,是不可以通过循环取值的。

  2.可迭代对象。

  当一个对象的内置方法中,有__iter__方法的都叫做可迭代对象。

  __iter__执行后,就是获取该对象的迭代器对象。

list1=[1,2,13,23,21]
set1={12,2,43,414,41,4,2}
str1=""
f=open('text1',mode='r',encoding='utf-8')
print(list1.__iter__())
print(set1.__iter__())
print(str1.__iter__())
print(f,f.__iter__())
#输出结果>>><list_iterator object at 0x000002016F6BBBE0>
#<set_iterator object at 0x000002016F6C1090>
#<str_iterator object at 0x000002016F6BBBE0>
#<_io.TextIOWrapper name='text1' mode='r' encoding='utf-8'> <_io.TextIOWrapper name='text1' mode='r' encoding='utf-8'>

  执行后获取的就是迭代器对象,对其进行数据类型转换也可以获得该列表。

  其中,f文件对象的__iter__(),获取后,和f原来的是一样的,所以,文件对象本身就是一个迭代器对象,迭代器对象的__iter__()还是它本身。

  判断一个对象是否是迭代器对象,需要满足两个条件:

  1。内部有__iter__(),方法。

  2.内部有__next__(),方法,

  所以可以得出,一个可迭代对象不一定是迭代器对象,而一个迭代器对象一定是个可迭代对象。

  __next__()所代表的就是对迭代器对象进行取值,当迭代器开始时需要进行初始化即把迭代器对象赋值给变量:

d=[1,2,3]
iter_d = d.__iter__()
print(d.__iter__().__next__())
print(d.__iter__().__next__())
print(d.__iter__().__next__())
#输出结果>>>1
#
#

  当迭代器对象不经过赋值变量就使用next取值时,会发现每次取值都是可迭代对象的第一个值,,因为d.__iter__()时迭代器对象,每一次使用都会对可迭代对象生成新的迭代器对象,所以一直是第一个值。

d=[1,2,3]
iter_d = d.__iter__()
print(iter_d.__next__())
print(iter_d.__next__())
print(iter_d.__next__())
#输出结果>>>1
#
#

  当其赋值给iter_d时,就可以对其进行迭代了,直到取值完后再取值就会报错,其错误提示是:

StopIteration

  这是一个异常,可以使用try: except语句对其进行异常处理:

while True:
try:
print(iter_d.__next__())
except StopIteration:
# print('输出结束')
break
#输出结果>>>1
#
#
#输出结束

  当语句成立不报错时,执行语句,当语句报错时,处理异常执行except后的语句。except后是需要处理的异常。

  迭代器取值的特点:只能往后依次取值,不能倒退取值。

  4.for循环内部的本质

  1.将in后面的对象调用__iter__转化为迭代器对象。

  2.使用___next__方法进行迭代取值。

  3.异常捕获并自动结束循环

  迭代取值的优点:1,不依赖于索引取值。2,内存中永远只占一份空间,不会溢出。  

  迭代取值的缺点:1,不能回去指定值,2,取完值后会报错。

  像内置方法中map,zip等方法,其返回值就是一个迭代器对象,这种方式永远只占一份内存,而python2中的这些方法所输出的就仅仅是可迭代对象,所耗内存比较大。

5。生成器

  本质:生成器就是一种用户自定义的迭代器。

  再普通函数中,其返回值使用return,而在生成器中,使用新的关键字yield。

  yield的功能是,当函数运行时,其中包函yield,加上()后就不会触发函数体内的代码运行。

def fun9():
print('')
yield 66
print('')
yield 77
print('')
yield 88
print('')
yield 99
iter1=fun9()
fun9()
iter1.__next__()
print(iter1,fun9,iter1.__next__())
#输出结果>>>111
#
#<generator object fun9 at 0x000002285BF96D58> <function fun9 at 0x000002285A351E18> 77

  拥有yield的函数中又以下特性:
  1.当函数名()时不会运行函数

  2.只有将函数名()赋值给一个变量时(初始化)才能取值

  3.运行iter1.__next__(),时会运行到yield前停下,

  4,函数名输出的是函数名,初始化赋值的是(函数名())迭代器对象,next打印的是yield后面的值。

  yield既可以返回一个值,也可以返回多个值,多个值按照元组返回。

  所以,yield满足以下特点:

  1.帮你提供了一种自定义生成器方式

  2.会帮你将函数的运行状态暂停住

  3.可以返回值

  return与yield的相同点:

  都可以返回一个或多个值

  不同点:

  yield可以返回多次值,而return只能返回一次。

  yield还可以接受外部传入的值:

def fun(name):
print('%s 输入数据'%name)
print('')
while True:
sj = yield
print('%s 已输入 %s'%(name,sj))
g = fun('lzx')
g.__next__()
g.send('')
g.send('')
#输出结果>>>lzx 输入数据
#
#lzx 已输入 11
#lzx 已输入 22

  当使用next运行生成器时,会运行到yield处,当yield被当成参数时,可以使用。send函数对其进行传参,并运行函数。

6.range

  range是一个可迭代对象,可以用yield手动实现其功能

def range1(x,y,s=1):
while x<y:
yield x
x+=s
for i in range1(1,10,1):
print(i)
#输出结果>>>1,2,3,4,5,6,7,8,9

7.生成器表达式:

  如同以下的生成式就是生成器表达式:

res=(i for i in range(1,10))
print(res)
print(res.__next__())
#输出结果>>><generator object <genexpr> at 0x000002B087176D58>
#

  注意,在生成器中,必须通过next触发代码运行,不会主动执行一行代码。

·面试题:

def add(n,i):
return n+i
def test():
for i in range(4):
yield i
g=test() for n in [1,10]:
g=(add(n,i) for i in g)
print(n)
res=list(g)
print(res)

  求其值。

  当for循环第一次运行时,n值为1所以g=(add(n,i) for i in test())

  当for循环第二次运行时,n值为10,所以g=(add(n,i) for i in (add(n,i) for i in test()))

  但test为迭代器对象,所以,在编写时不会运行,只有在for循环中 遇到next函数时才会运行,那时候的i值已经时10,所以将10带入,结果为:

[20, 21, 22, 23]

  题2:

def multipliers():
return [lambda x: i*x for i in range(4)]
print([m(2) for m in multipliers()])

  其中可以将匿名函数分解成闭包函数:

def outter():
list1=[]
for i in range(4):
def func(x):
return x*i
list1.append(func)
return list1

  在闭包函数的延迟绑定,当函数调用之前,内函数中的变量都不会绑定,函数运行时才会进行绑定,所以最后的i值为3,答案时【6,6,6,6】

  要使得参数传入,需要在内函数参数中添加i:

def outter():
list1=[]
for i in range(4):
def func(x,i=i):
return x*i
list1.append(func)
return list1 print([m(2) for m in outter()])

  最后结果为[0,2,4,6]

  题3:

  在文件中使用生成器,计算每行的个数。:

  如果使用list存储每一行的字符个数,就需要在内存中存储大量数据:

with open('text7.txt',mode='w',encoding='utf-8') as f:
for i in range(0,1000):
f.write("www.%s.com"%(i)+"\n") def func(file):
with open(file,mode='r',encoding='utf-8') as f:
list2=[]
list2.append(len(f.readline()))
return list2
print(func('text7.txt'))

  对内存的损耗非常大,所以可以使用生成器,然后对其迭代取值。

res2 = (len(line) for line in open('test1.txt', 'r', encoding='utf-8'))
print(res2) # <generator object <genexpr> at 0x000002B3748FD0A0>
print(next(res2))
print(next(res2))

  题4:

def demo():
for i in range(4):
yield i
g=demo()
g1=(i for i in g)
g2=(i for i in g1)
print(list(g1))
print(list(g2))

  当g1开始执行是,for循环将其内部指针一一指向g=demo(),所以,当g2,对g1进行遍历时就是个空列表所以答案是:

[0, 1, 2, 3]
[]

day13_7.15 迭代器和生成器的更多相关文章

  1. 15.python的for循环与迭代器、生成器

    在前面学习讲完while循环之后,现在终于要将for循环这个坑填上了.之所以拖到现在是因为for循环对前面讲过的序列.字典.集合都是有效的,讲完前面的内容再来讲for循环会更加容易上手. 首先,for ...

  2. python基础15上_迭代器_生成器

    # 迭代器和生成器 # 迭代器: # 双下方法 : 很少直接调用的方法.一般情况下,是通过其他语法触发的 # 可迭代的 —— 可迭代协议 含有__iter__的方法('__iter__' in dir ...

  3. Python之模块,迭代器与生成器

    本节涉及内容: 1. 迭代器和生成器 2. 递归 3. 字符串格式化 4. 模块 内置模块 自定义模块 第三方模块 5. 序列化的模块 json pickle (一). 迭代器和生成器: 迭代器:  ...

  4. Python中的迭代器和生成器

    本文以实例详解了python的迭代器与生成器,具体如下所示: 1. 迭代器概述: 迭代器是访问集合元素的一种方式.迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束.迭代器只能往前不会后 ...

  5. python的迭代器、生成器、装饰器

    迭代器.生成器.装饰器 在这个实验里我们学习迭代器.生成器.装饰器有关知识. 知识点 迭代器 生成器 生成器表达式 闭包 装饰器 实验步骤 1. 迭代器 Python 迭代器(Iterators)对象 ...

  6. Python编程四大神兽:迭代器、生成器、闭包和装饰器

    生成器 生成器是生成一个值的特殊函数,它具有这样一个特点:第一次执行该函数时,先从头按顺序执行,在碰到yield关键字时该函数会暂停执行该函数后续的代码,并且返回一个值:在下一次调用该函数执行时,程序 ...

  7. Python_迭代器、生成器、列表推导式,生成器表达式

    1.迭代器 (1)可迭代对象 s1 = ' for i in s1: print(i) 可迭代对象 示例结果: D:\Python36\python.exe "E:/Python/课堂视频/ ...

  8. python之迭代器与生成器

    python之迭代器与生成器 可迭代 假如现在有一个列表,有一个int类型的12345.我们循环输出. list=[1,2,3,4,5] for i in list: print(i) for i i ...

  9. Python—迭代器与生成器

    迭代器与生成器 生成器(generator) 先来了解一下列表生成器: list = [i*2 for i in range(10)] print(list)>>>>[0, 2 ...

随机推荐

  1. Tomca原理分析之责任链

    责任链使用位置:Container处理请求 Container处理请求是使用Pipeline-Valve管道来处理的!(Valve是阀门之意) Pipeline-Valve是责任链模式,责任链模式是指 ...

  2. rapoo mt700键盘mac osx不能复制问题

    问题描述:rapoo mt700键盘mac osx,按windows建+c不能复制,其它按键正常 解决办法:检查右上角windows等是否亮,如果是亮着按FN+WIN 切换模式 操作方法: 有线模式: ...

  3. 详解 IaaS、PaaS和SaaS 以及他们各自的代表公司

    ——IaaS,PaaS和SaaS 是云计算领域的专业术语,也是云计算的三种服务模式.   (1)SaaS:Software as a Service,软件即服务(也称为云应用程序服务) . 云市场中企 ...

  4. 从游击队到正规军:马蜂窝旅游网的IM系统架构演进之路

    本文引用自马蜂窝公众号,由马蜂窝技术团队原创分享. 一.引言 今天,越来越多的用户被马蜂窝持续积累的笔记.攻略.嗡嗡等优质的分享内容所吸引,在这里激发了去旅行的热情,同时也拉动了马蜂窝交易的增长.在帮 ...

  5. tf.ConfigProto()

    tf.ConfigProto一般用在创建session的时候用来对session进行参数配置 with tf.Session(config=tf.ConfigProto(...)...) tf.Con ...

  6. linux软链接

    这是linux中一个非常重要的命令,他的功能是为某一个文件在另一个位置建立一个同步的链接,这个命令最常用的参数是-s, 具体用法是: ln -s 源文件 目标文件 当我们需要在不同的目录,用到相同的文 ...

  7. fastadmin表单提交后却没有关闭弹窗

    点击操作按钮弹出窗口,操作完之后提交表单,无论操作成功还是失败,窗口都不关闭,操作之后出现一个笑脸,3秒后回到弹框刚打开的样子 而我们想要的是这个效果: 在jS那里给这个按钮绑定一个事件即可实现

  8. redis之主从同步

    很多企业都没有使用到 Redis 的集群,但是至少都做了主从.有了主从,当 master 挂掉的时候,运维让从库过来接管,服务就可以继续,否则 master 需要经过数据恢复和重启的过程,这就可能会拖 ...

  9. jvm的组成入门

    JVM的组成分为整体组成部分和运行时数据区组成部分. JVM的整体组成 JVM的整体组成可以分为4个部分:类加载器(Classloader).运行时数据区(Runtime Data Area).执行引 ...

  10. jmeter入门操作 = 录制

    没安装工具的朋友请先看:https://www.cnblogs.com/cainiaoxiansheng/p/11007754.html 软件装好,功能了解好,那么就开始进入正题,先来一波录制 不要鄙 ...