迭代器、生成式、生成器

目录:

  迭代器

  生成器

  生成式

  三元表达式

  for循环原理

概要:

生成式:一次性生成所有数据,然后保存在内存中,适合小量数据
生成器:返回一个可迭代对象,生成器generator对象,必须通过遍历才能一一将值取出
生成器不会一次列出所有的数据,next()一次,给一个值,更加节省内存使用率
可迭代对象(iterable):可以通过for循环调用出来的,就是可迭代对象,如:列表、元组、字典、生成式、生成器
迭代器(iterator):任何具有__next__()方法的对象都是迭代器,对迭代器调用next()方法可以获取下一个值

迭代器:

1. 什么是迭代器 
    迭代指的是一个重复的过程,每一次重复都是基于上一次的结果而来的
      迭代器指的是迭代取值的工具,该工具的特点是可以不依赖于索引取值
#原始的迭代方法
    li=['a','b','c','d','e']
    li=('a','b','c','d','e')
    li='hello'

    i=0
    while i < len(li):
        print(li[i])
        i+=1

2. 为何要用迭代器
为了找出一种通用的&可以不依赖于索引的迭代取值方式

3. 如何用迭代器
可迭代的对象:但凡内置有.__iter__方法的对象都称之为可迭代的对象
迭代器对象:既内置有__iter__方法,又内置有__next__方法
关于__iter__方法:
调用可迭代对象的__iter__会得到一个迭代器对象
调用迭代器对象的__iter__会得到迭代器本身

4. 总结迭代器的优缺点:
优点:
1. 提供了一种通用的&可以不依赖于索引的迭代取值方式
2. 同一时刻在内存中只有一个值,更加节省内存(老母鸡,Python3的rang()方法就相当于一只老母鸡)

缺点:
1. 取指定值不如索引灵活,并且迭代器是一次性的
2. 无法预知迭代器数据的个数
迭代器对象:

  可迭代的对象: str,list,tuple,dict,set,文件对象(除了数字类型)
  迭代器对象: 文件对象
  可迭代的对象=====》迭代器对象:调用可迭代对象内置的__iter__方法会有一个返回值,该返回值就是对应的迭代器对象
#基本语法
dic={'x':1,'y':2,'z':3} iter_dic=dic.__iter__() print(iter_dic) #<dict_keyiterator object at 0x0000000001D97728> res1=iter_dic.__next__() print(res1) #x
res2=iter_dic.__next__()
print(res2)

res3=iter_dic.__next__()
print(res3)
#超出迭代器数据个数,报错
res4=iter_dic.__next__()
print(res4)
print(dic.__iter__().__next__())#x
print(dic.__iter__().__next__())#x
print(dic.__iter__().__next__())#x

通过循环来捕捉异常,避免取值越界后报错:
 1 dic={'x':1,'y':2,'z':3}
 2 # dic=['a','b','c']
 3 iter_dic=dic.__iter__()
 4 
 5 iter_dic=open(r'今日内容',mode='rt',encoding='utf-8')#文件为迭代器对象
 6 
 7 while True:
 8     try:
 9         print(iter_dic.__next__())
10     except StopIteration:
11         break

 for循环原理:

for准确地说应该是迭代器循环,for循环的原理如下:
  1. 先调用in后面那个值的__iter__方法,得到迭代器对象
  2. 执行迭代器.__next__()方法得到一个返回值,然后赋值给一个变量k,运行循环体代码
  3. 循环往复,直到迭代器取值完毕抛出异常然后捕捉异常自动结束循环
 1 dic={'x':1,'y':2,'z':3}
 2 iter_dic=dic.__iter__()
 3 print(iter_dic)
 4 print(iter_dic.__iter__())
 5 
 6 for k in dic: # iter_dic=dic.__iter__() | k=iter_dic.__next__()
 7     print(k)
 8 # <dict_keyiterator object at 0x0000000000477728>
 9 # <dict_keyiterator object at 0x0000000000477728>
10 # x
11 # y
12 # z
with open(r'今日内容',mode='rt',encoding='utf-8') as f:
for line in f: #iter_f=f.__iter__()
print(line)

 自定义迭代器:

yield关键字:只能用在函数内
  在函数内但凡包含有yield关键字,再去执行函数,就不会立刻运行函数体代码了,会得到一个返回值,该返回值称之为生成器对象,生成器本质就是迭代器

总结yield:
  1. 提供一种自定义迭代器的解决方案
  2. yield可用于返回值

yield VS return

相同点:都可以用于返回值
不同点:yield可以暂停函数,yield可以返回多次值,而return只能返回值一次值函数就立刻终止

 1 def func():
 2     print('=====>第一次')
 3     yield 1
 4     print('=====>第二次')
 5     yield 2
 6     print('=====>第三次')
 7     yield 3
 8     print('=====>第四次')
 9 
10 g=func()
11 print(g.__iter__().__iter__().__iter__() is g)
12 iter(g) #g.__iter__()
13 res=next(g) #g.__next__()
14 print(res)
15 
16 res1=next(g)
17 print(res1)
18 
19 res2=next(g)
20 print(res2)
21 
22 res3=next(g)     #报错,取不到
23 print(res3)
24 # True
25 # =====>第一次
26 # 1
27 # =====>第二次
28 # 2
29 # =====>第三次
30 # 3
31 # =====>第四次
 自定义一个rang函数:
def my_range(start,stop,step=1):
    while start < stop:
        yield start
        start+=step

res=my_range(1,5,step=2) # 1 3
print(next(res))    #1
print(next(res))    #3
for item in res:     #还在同一个迭代器中,此时res已经到3,步长为2,没有下一个值
    print(item)     #打印不到结果


for item in my_range(1,5,2):    #这是一个新的迭代器
    print(item)    #1,3

三元表达式:

原始操作:
def max2(x,y):
    if x > y:
        return x
    else:
        return y

简化操作:
x=10
y=20
res=x if x > y else y
print(res)

XXX生成式:

 

 列表生成式:列表

将大于4的数字添加到egg后,存入列表:

#原始操作:
l=[]
for i in range(1,11):
    if i > 4:
        res='egg%s' %i
        l.append(res)
print(l)
#简化操作:
l=['egg%s' %i for i in range(1,11) if i > 4]
print(l)
#['egg5', 'egg6', 'egg7', 'egg8', 'egg9', 'egg10']

 将除了egon外的名字后加上_DSB,然后存入一个列表:

#原始操作:
names=['egon','lxx','yyx','cw','alex','wxx']
l=[]
for name in names:
    if name != 'egon':
        res='%s_DSB' %name
        l.append(res)
print(l)
#简化操作:
l=['%s_DSB' %name for name in names if name != 'egon']
print(l)
#['lxx_DSB', 'yyx_DSB', 'cw_DSB', 'alex_DSB', 'wxx_DSB']

字典生成式:字典

items=[('name','egon'),('age',18),('sex','male')]
#原始方法: dic={} for k,v in items: dic[k]=v print(dic)
#简化方法: res={k:v for k,v in items if k != 'sex'} print(res)   #{'name': 'egon', 'age': 18} res={i for i in 'hello'} print(res)
#{'o', 'h', 'e', 'l'} 去重,逐个,无序

生成器表达式(实际也是一个迭代器):

res=(i**2 for i in range(3))
print(res)    #本身是一个迭代器,只有调用next方法,才能取到值,什么也不会打印
print(next(res))
print(next(res))
print(next(res))
#0
#1
#4

 

 1 with open(r'今日内容',mode='rt',encoding='utf-8') as f:
 2     data=f.read()
 3     print(len(data)) #1025
 4 
 5 with open(r'今日内容', mode='rt', encoding='utf-8') as f:
 6     res=0
 7     for line in f:
 8         res+=len(line)
 9     print(res)#1025
10 
11 with open(r'今日内容',mode='rt',encoding='utf-8') as f:
12     res=sum((len(line) for line in f))
13     # res=sum(len(line) for line in f)#有双重小括号,可以省略一个
14     print(res)
15 
16 with open(r'今日内容', mode='rt', encoding='utf-8') as f:
17     res=max([len(line) for line in f])  #60
18     #res=max((len(line) for line in f))  #60
19     #res=max(len(line) for line in f)    #60
20     print(res)

 

posted @ 2018-09-28 22:28  ChuckXue  阅读(435)  评论(0编辑  收藏  举报