码迷,mamicode.com
首页 > 其他好文 > 详细

迭代器和生成器

时间:2019-07-16 00:05:19      阅读:98      评论:0      收藏:0      [点我收藏+]

标签:表达   username   调用   turn   查看   十进制   字符串   这不   四舍五入   

一、迭代器:iterable(可迭代的,可重复的)

      就是更新重复的过程,每次的迭代都必须基于上一次的结果,内部都是基于for 循环原理

  为什么要用迭代器:迭代器提供了一个不需要按索引取值的方式

只是简单的重复,没有更新内容这不算是迭代

n = 0
 while True:
     print(n)
l=[1,2,3,4,5]
count=0
while count<len(l):
    print(l[count])
    count+=1
 上述例子就是一个完整的迭代过程

 二、什么是可迭代对象
  可迭代对象指的是内置有__iter__方法的对象,例如:atr 字符串   list 列表  tuple 元组   set 集合    dict  字典 

       文件对象也是(执行内置的__iter__之后还是本身,没有任何变化,文件对象本身就是迭代器对象

l2=(1,2,3)
res=l2.__iter__()
print(res)
执行的结果:<tuple_iterator object at 0x000001E48B5BE940>

l3
={a:1} l3.__iter__() l4={a,b} l4.__iter__()
f=open(‘03.txt‘,‘w‘,encoding=‘utf-8‘)
 f.__iter__()

  可迭代对象执行内置的__iter__方法得到就是该对象的迭代器对象

三、迭代器对象:

  迭代器对象:可以用next获取下一个值(说明实现了next方法),但是每个值只能获取一次,单纯的迭代器没有实现iter魔法函数,所以不能使用for循环

  指的是即内置有__iter__又内置有__next__方法的对象,必须同时满足这两个条件

        迭代器一定是可迭代对象,而可迭代对象不一定是迭代对象

  文件类型是迭代器对象 

f=open(‘03.txt‘,‘w‘,encoding=‘utf-8‘)
res1=f.__iter__()
res2=f.__exit__()
print(res1,res2)

1:迭代器的取值调用  __next__

p=[1,2,3,4,5]
iter_p=p.__iter__() # 先生成一个迭代器对象,才可以调用

迭代器的取值 调用 ——next——
print(iter_p._next_())
# 次数超过容器类型 print(iter_l.__next__()),如果取完了 直接报错

 d = {name:gason,password:123,hobby:write}
    # 将可迭代对象d转换成迭代器对象,才可被调用
 iter_d = d.__iter__()
 #迭代器对象的取值 必须用__next__
 print(iter_d.__next__())
 print(iter_d.__next__())
 print(iter_d.__next__())
 print(iter_d.__next__())  # 取完了 报错StopIteration

 

技术图片

打开文件:
f1=open(03.txt,r,encoding=utf-8)
iter_f=f1.__iter__()
print(iter_f is f1)

注:迭代器对象无论执行多少次__iter__方法得到的还是迭代器对象本身

  迭代器取值的特点: 只能依次往后取  不能倒退  取完就会报错

2、迭代取值的有缺点
    优点:
        1.不依赖于索引取值
        2.内存中永远只占一份空间,不会导致内存溢出
   
    缺点:
        1.不能够获取指定的元素
        2.取完之后会报StopIteration(停止迭代)的错

 

四、for 循环的本质:

    1:将in后面的可迭代对象调用__iter__转换成迭代器对象

    2:调用了__next__迭代的取值方法

    3:内部有异常捕获StopIteration(停止迭代)超出了范围,,当__next__报这个错,自动结束循环

l=[1,2,3,4]
res=map(lambda x:x+1,l)
print(res.__next__())
print(res.__next__())
print(res.__next__())
print(res.__next__())

技术图片

 

五、生成器:人为自定义实现迭代的功能就叫生成器 

关键字:  yield  

函数内如果有yield关键字,那么加括号执行函数的时候并不会触发函数体代码的运行 ,程序中遇到yield会暂停运行等待调入参数 

def func():
    print(one)
    yield  12   #程序调用函数执行到 yeild 后就会终止
    print(two)
    yield
    print(three)
res=func()
print(res.__next__())

结果
>>>one 
>>>12
如果yrilde 后面不传参数的话 返回 None

 

 

  利用关键字‘yiled’ 用函数实现 range 原理:

print(range(1,10))

def my_range(start,end,step=1):
    while start<end:
        yield start
        start+=step
for j in my_range(1,10):# 循环打印输出1—10
    print(j)

六、了解:   yield表达式的形成

    利用函数调用的特性和yield的本质在函数中的运用

def inner(name):
    print(my name is %s%name)
    while True:
        like=yield  # 如果不传值就结束程序
        print(i like%s%like)
def func():
    pass
res=inner(kevin)
res.__next__()# 必须先将代码运行至yiled 才能够为其传值
res1=res.inner(write) # 调用__next_才能执行yiled后面的语句
print(res)

 

yield
    1.帮你提供了一种自定义生成器方式
    2.会帮你将函数的运行状态暂停住
    3.可以返回值

 

与return之间的区别
    相同点:都可以返回值,并且都可以返回多个
    不同点:
        yield可以返回多次值,而return只能返回一次函数立即结束
        yield还可以接受外部传入的值

 七、生成器表达式:

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

          #生成器表达式 sum(i for i in range(100000000))#几乎不占内存

res=[i for i in range(1,10) if i!=4]
print(res)
#全部打印输出1—10

res1=(i for i in range(1,10000) if i!=4) #生成器表达式
print(res1)
# next=res.__iter__() print(res1.__next__())
print(res1.__next__())
print(res1.__next__())
print(res1.__next__())
# 必须通过触发—next—才会触发

 

生成器面试题:

def demo():
    for i in range(4):
        yield i  # i=[0,1,2,3]  # 遇到—next--才会触发执行 

g=demo()

g1=(i for i in g)  #  for 循环取值赋值给g1,已经取完i中的内存地址
g2=(i for i in g1)

print(list(g1))
print(list(g2))

结果:
>>>[0,1,2,3]
>>>[]

 

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)
    # 第一次for循环g=(add(n,i) for i in test())

    # 第二次for循环g=(add(n,i) for i in (add(n,i) for i in test()))
print(n)
res=list(g)

"""
for i in (add(10,i) for i in test()):  会执行所有的生成器内部的代码
    add(n,i)
"""

结果输出是:20 21 21 23

循环执行完第一次 n=10

八、内置函数: Python中提供了68个内置函数

技术图片

 

 常用的内置函数执行:

 

1.abs:绝对值

i=-1.12
print(abs(i))  #  负数转正

 

2.all(全部)  any (部分)

l = [0,1,0]
 print(all(l))  # 只要有一个为False就返回False
 print(any(l))  # 只要有一个位True就返回True

 

3.locals(当地)  美 [‘lo?klz]   globals(全球)

def index():
    username = 我是局部名称空间里面的username
    print(locals())  # 当前语句在哪个位置 就会返回哪个位置所存储的所有的名字
    #print(globals())  # 无论在哪 查看的都是全局名称空间地址
index()

技术图片

 

4. bin(二进制)  oct(八进制) hex(十六进制)  int(整形)

print(bin(10)) # 转换为二进制
 print(oct(10))
 print(hex(10))
print(int(0b1010,2))  #二进制转换为十进制

技术图片

 

 

5、布尔值bool  只有两种结果True False       True= 0,空,None

6、bytes  打印字节数

7、callable     adj.  可随时支取的,请求即付的,随时可偿还的

可调用的(可以加括号执行相应功能的)
 l = [1,2,3] def index():     pass print(callable(l)) print(callable(index))

8、chr  ord   字符的转换

 print(chr(97))  # 将数字转换成ascii码表对应的字符
 print(ord(a))  # 将字符按照ascii表转成对应的数字

9、divmod  分页器

print(divmod(101,10))  # 爬虫

10、enumerate 枚举

l = [a,b]
for i,j in enumerate(l,1):# 枚举按编号取值 1是初始值,不写默认为0
    print(i,j)

结果:
>>>1  a
>>>2   b

应用场景是购物车 按序号选功能

11、 format 三种玩法:
 {}占位   #格式化输出,和%s %d一样的原理
{index} 索引 
 {name} 指名道姓  # 字典中用到

12、type isinstance 判断数据类型

 n = 12
 print(type(n))
print(isinstance(n,list))  # 判断对象是否属于某个数据类型

13、pow 幂运算

print(pow(2,3))   >>> 2**3

14、help 查看内置原理

15、print(round(3.4))  把…四舍五入;

 

 

 

 

 

 

 

 

 


  

 

 




 

 

 

 

 

 

 

 

 

 

生成器:函数中只要有yield,这个函数就会变成生成器。每次运行到yield的时候,函数会暂停,并且保存当前的运行状态,返回返回当前的数值,并在下一次执行next方法的时候,又从当前位置继续往下走。

迭代器和生成器

标签:表达   username   调用   turn   查看   十进制   字符串   这不   四舍五入   

原文地址:https://www.cnblogs.com/Gaimo/p/11189754.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!