zoukankan      html  css  js  c++  java
  • 迭代器与生成器

    一.迭代器

    1.什么是迭代器

    迭代:更新换代的过程,前一次循环的终止条件是后一次循环的初始条件。

    迭代器:迭代取值的过程。

    2.为什么要用迭代器

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

    3.怎么用迭代器

    可迭代对象(iterable) :有内置方法__iter__          ps:补充:针对双下线开头双下划线结尾的方法,推荐读:双下+方法名

    基本类型中的可迭代对象有:str,tuple,list,dict,set和文件对象(文件对象本身就是一个迭代器对象)

    str = "12123"
    lis = [1,2,3,4,5]
    tup = (1,2,3,4)
    dic = { "stevin" : "male"}
    se = { 1,2,3,4}
    with open("a.txt", "at",encoding="utf-8") as f :
        print(f.__iter__())
    
    
    print(str.__iter__())
    print(lis.__iter__())
    print(tup.__iter__())
    print(dic.__iter__())
    print(se.__iter__())
    View Code

    迭代器(iterator):具有内置方法__iter__   和__next__   .  ps:迭代器一定是可迭代对象,可迭代对象不一定是迭代器对象。

            同时具有内置方法__iter__方法和内置方法__next__的可迭代对象,可以通过__iter__方法得到就是该对象的迭代器对象

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

    迭代器的取值必须使用__next__

    迭代器的特点:只能按照次序向后取值,不能后退。

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

    缺点
    1.不能够获取指定的元素
    2.取完之后会报StopIteration错

    异常处理:当迭代器中的值被取完后,再用__next__取值会报出StopIteration异常

    解决方法: try : 报错语句

         except StopIteration : 捕获异常后的操作

    l = [1,2,3,4]
    l = l.__iter__()
    while True :
        try:
            print(l.__next__())
        except StopIteration :
            break
    View Code

    二.for循环的本质

    for循环内部的本质
    1.将in后面的literable对象调用__iter__转换成迭代器对象
    2.调用__next__迭代取值
    3.内部有异常捕获StopIteration,当__next__执行报错时,自动结束循环

    三.生成器

    生成器:个人自定义的迭代器,生成器的本质就是迭代器(具有__iter__   和__next__两个内置方法)

    生成器的定义与函数的定义类似,使用yield代替return来进行返回结果。

    def func() :
        print("first")
        yield 111   #yield后面跟的是调用迭代器__next__方法返回的值
        print("second")
        yield 222,"aaaa","bbbb"
        print("third")
        yield 333
        print("fourth")
        yield 444
    
    res = func() # 有yield函数名加(),不会让函数运行
    # 而是生成器初始化,把函数变为迭代器对象。
    print(res.__next__()) #返回一个值
    print(res.__next__()) #以元祖的形式返回多个值
    print(res.__next__())
    View Code

    yield外界传参

    def dog (name) :
        print("%s 准备开吃" %name)
        while True:
            food = yield
            print('%s 吃了 %s' % (name, food))
    
    g = dog('stevin')
    g.__next__()     # 必须在运行代码yield时,才能进行传值
    g.send('大骨头')  # 给yield左边的变量传参  触发了__next__方法
    g.send('饺子')
    g.send('饺子')
    View Code

    生成器表达式:

    格式:(变量名 for 变量名  in 容器类型 if 判断条件)

    with open("b.txt", "rt",encoding="utf-8") as f :
        res = (len(line) for line in f)   # 生成器表达式
        print(sum(res))
    View Code

    生成器不会主动执行任何一行代码,必须通过__next__触发代码的运行

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

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

    四.内置方法

    print(abs(-13.24))  # abs 求绝对值
    
    l = [1,1,0]
    print(all(l))  # all 存在一个为False就返回False
    print(any(l))  # any 任意一位为True就返回True
    
    def index():
    
        username = '我是局部名称空间里面的username'
        print(locals())   # locals 返回当前所在区域存储的所有的名字
        print(globals())  # globals 无论在哪 返回的都是全局名称空间
    index()
    
    print(bin(10))  # bin 十进制转2进制
    print(oct(10))  # oct 十进制转8进制
    print(hex(10))  # hex 十进制转16进制
    print(int('0b1010',2))  # 其他进制转十进制
    
    print(bool(1))
    print(bool(0)) # bool判断真假
    
    
    s = 'hello你好'
    print(s.encode('utf-8'))  # encode 编码
    print(bytes(s,encoding='utf-8'))   # 字节流
    
    def index():
        pass
    
    print(callable(index))  # callable 可调用的(可以加括号执行相应功能的)
    
    
    print(chr(65))  #  chr 将数字转换成ascii码表对应的字符
    print(ord('A'))  # ord 将字符按照ascii表转成对应的数字
    
    
    print(dir(range(12))) # dir 获取当前对象名称空间里面的名字
    
    
    
    
    print(divmod(101,10))
    total_num,more = divmod(900,11)
    if more:
        total_num += 1
    print('总页数:',total_num)#  divmod  分页器
    
    
    l = ['a','b','c','d']
    for i,j in enumerate(l,1):# enumerate 枚举
        print(i,j)
    
    # eval  exec 执行字符串表达式
    
    s1 = """
    print(1 + 2)
    for i in range(10):
        print(i)
    """
    # eval(s1)
    exec(s1)
    
    
    name = 'jason'
    s2 = """
    name
    """
    print(eval(s2))  # eval不支持逻辑代码,只支持一些简单的python代码
    
    
    def login():
        """
        一起嗨皮
        :return:
        """
    print(help(login))  # help 查看函数注释
    
    
    
    print(isinstance("123",list))  # isinstance 判断对象是否属于某个数据类型
    
    print(pow(2,3)) # 返回 x的y次方。
    
    
    print(round(3.4))  # round 四舍五入,取整
    View Code

    五.面向过程编程

    面向过程编程:类似与流程化设计
    好处:
    将复杂的问题简单化,流程化
    坏处:
    可扩展性较差 一旦需要修改 整体都会受到影响

    六.面试题

    def multipliers():
    
        return [lambda x : i*x for i in range(4)]
    
    print([m(2) for m in multipliers()])
    
    #  扩展版
    def multipliers2():
        list1 = []
        for i in range(4):
    
            def func(x):
            #应该这么修改:def func(x, i=i):
    
                return x * i
    
            list1.append(func)
    
        return list1
    
    print([m(2) for m in multipliers2()])
    View Code
  • 相关阅读:
    创业公司技术总监,去上市公司面试,结果凉了!
    Java开发最常犯的10个错误,打死都不要犯!
    这 17 个 JVM 参数,高级 Java 必须掌握!
    推荐几个顶级的IT技术公众号,坐稳了!
    Spring Boot 面试,一个问题就干趴下了!(下)
    密码已进入"淘汰"倒计时!
    一条简单的 SQL 执行超过1000ms,纳尼?
    天天用Synchronized,底层原理是个啥?
    为什么很多程序员工作时都戴耳机?
    Java转型大数据开发全套教程,都在这儿!
  • 原文地址:https://www.cnblogs.com/Cpsyche/p/11192146.html
Copyright © 2011-2022 走看看