函数迭代器与生成器

迭代器

什么是迭代器?

  迭代:更新换代(重复)的过程,每次的迭代都必须基于上一次的结果

  迭代器:迭代取值的工具

为什么要用?

  迭代器给你提供了一种不依赖与索引取值的方式

n = 0
while True:
    print(n)
#这就是不算是迭代器,只是简单的重复

l = [1,2,3,4]
s = 'hello'
n = 0
while n < len(s):
    print(n)
    n+=1
#重复+每次迭代都是基于上一次的结果而来的

需要迭代取值的数据类型:

  字符串

  列表

  元组

  字典

  集合

可迭代对象:只要内置有__iter__方法的都叫做可迭代对象

基本数据类型中是可迭代的对象有:

  str    list    tuple  set   dict

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

s = 'hello'
l = [1,2,34,]
t = (1,2,34)
s1 = {1,2,3,4}
d = {'name':'jason'}
f1 = open('xxx.txt','w',encoding='utf-8')

res = s.__iter__()  # res = iter(s)
print(s.__len__())  # 简化成了len(s)
res1 = l.__iter__()  # res1 = iter(l)
res2 = f1.__iter__()  # res2 = iter(f1)
print(res,res1,res2)
print(f1)

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

迭代器的取值

迭代器对象:

  1.内置有__iter__方法

  2.内置有__next__方法

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

l = [1,2,3,4]
iter_l = l.__iter__() #生成一个迭代器对象

#迭代器取值调用__next__
print(iter_l.__next__())
print(iter_l.__next__())
print(iter_l.__next__())
print(iter_l.__next__())
print(iter_l.__next__())  #如果取完了  直接报错

d = {'name':'yzy','sex':'male'}
#将可迭代对象d转换成迭代器对象
iter_d = d.__iter__()
#迭代器对象的取值必须用__next__
print(iter_d.__next__())
print(iter_d.__next__())
print(iter_d.__next__()) #取完了  报错StopIteration

迭代器对象无论执行多少次__iter__方法得到的还是迭代器对象本事(******)

d = {'name':'jason','password':'123','hobby':'泡m'}
iter_d = d.__iter__()

#异常处理
while True:
    try:
        print(iter.d__next__())
    except StopIteration:
        print('no')
        break
d = {'name':'jason','password':'123','hobby':'泡m'}
iter_d = d.__iter__()

#异常处理
while True:
    try:
        print(iter.d__next__())
    except StopIteration:
        print('no')
        break

迭代器取值的特点:

  只能往后依次取,不能后退

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

d = {'name':'jason','password':'123','hobby':'泡m'}
for i  in d:
    print(i)
#for循坏后面的in关键  跟的是一个可迭代对象

 for循坏内部的本质

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

  2.调用__next__迭代取值

  3.内部有异常捕获StopIteration,当__next__报这个错  自动结束循坏

可迭代对象:内置有__iter__方法

迭代器对象:既内置有__iter__也有内置__next__方法

迭代取值:

  优点:

    1.不依赖与索引取值

    2.内存中永远只占一份空间,不会导致内存溢出

  缺点:

    1.不能够获取指定的元素

    2.取完之后会报StopIteration错

生成器

  用户自定义的迭代器,本质上就是迭代器

 def func():
     print('first')
     yield  666  # 函数内如果有yield关键字,那么加括号执行函数的时候并不会触发函数体代码的运行
     print('second')
     yield  777
     print('third')
     yield  888
     print('forth')
     yield
     yield

#yield 后面跟的值就是调用迭代器__next__方法你能得到的值
#yield既可以返回一个值也可以返回多个值,并且多个值也是按照元组的形式返回
g = func()#生成器初始化:将函数变成迭代器
print(g)
print(g.__next__())
print(g.__next__())
print(g.__next__())
print(g.__next__())
print(g.__next__())

#yield支持外界为其传参

def dog(name):
    print('%s 准备开吃'%name)
    while True:
        food = yield
        print('%s 吃了 %s'%(name,food))
当函数内有yield关键字的时候,调用该函数不会执行函数体代码
而是将函数变成生成器
g = dog('yyy')
g.__next__()  # 必须先将代码运行至yield 才能够为其传值
g.send('apple')  # 给yield左边的变量传参  触发了__next__方法

yield

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

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

  3.可以返回值

与return之间的异同点:

  相同点:都可以返回值,都可以返回多个

  不同点:

    yield可以返回多次值,而return只能返回一次函数立即结束

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

生成器表达式

res = (i for i in range(1,100) if i != 4)  #生成器表达式

#生成器不会主动执行任何一行代码,必须通过__next__触发代码的运行
print(res.__next__())
print(res.__next__())
print(res.__next__())
print(res.__next__())
with open('name.txt','r',encoding='utf-8')as f:
    n = 0 
    for line in f:
        n += len(line)
    print(n)


g = (len(line) for line in f)
print(g.__next__())
print(g.__next__())
print(g.__next__())
print(sum(g))

常用的内置方法

abs()#求绝对值

abs(-1)

print(bin(10))  #2进制
print(oct(10))   #8进制
print(hex(10))   #16进制 
print(int('0b1010',2)    #将2进制转换成10进制

callable()#判断是否可调用

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

dir 获取当前对象名称空间里面的名字
l = [1,2,3]
print(dir(l))

divmod  分页器
print(divmod(100,10))

total_num,more = divmod(900,11)
if more:
    total_num += 1
print('总页数:',total_num)

enumerate 枚举
l = ['a','b']
for i,j in enumerate(l,1):
    print(i,j)

eval exec
s = """
print('hello baby')
x = 1
y = 2
print(x+y)
"""
eval(s)
exec(s)
#eval 不支持逻辑代码,只支持一些简单的python代码

isinstance  判断对象是否属于某个数据类型
n = 1
print(inistance(n,int))

pow
print(pow(2,3))  #8

round
print(round(3.4))   # 3
print(round(3.6))    #4

面向过程编程:就类似与设计一条流水线

  好处:

    将复杂的问题流程化  从而简单化

  坏处:

    可扩展性较差  一旦需要修改   整体都会受到影响

原文地址:https://www.cnblogs.com/KrisYzy/p/11190156.html