zoukankan      html  css  js  c++  java
  • 上海day13 -- 迭代器,生成器以及常用内置方法

    目  录

    一、迭代器

    二、for 循环原理

    三、生成器

    四、常用内置方法

    一、迭代器

    解释:迭代就是在前一次的结果上重复取值,器就是工具。迭代器就是迭代取值的工具。

    1、为什么要用迭代器?

      迭代器不需要依赖索引取值。

    2、可迭代对象:

      内置只有__iter__方法的叫做可迭代对象。

    3、迭代器对象:

      内置不仅有__iter__方法,还有__next__方法的叫做迭代器对象。

    注意:可迭代对象通过__iter__方法得到迭代器对象,迭代器对象通过__next__方法取值。

    4、基本数据类型有哪些可迭代对象?

      可迭代对象即内置有__iter__方法的数据类型,

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

    以上实验可知:str, list, dict, tuple, set, f  都内置有__iter__方法,

           特别是文件对象f 不仅有 __iter__方法还有__next__方法,说明文件对象不仅是可迭代对象还是迭代器对象。

    补充小知识:

      针对双下划线开头双下划线结尾的方法,python推荐读法:双下+方法名

      Python解释器为我们定制了快捷方法来代替双下划线__:

        __iter__ 等价于 iter()

        __len__ 等价于 len()

        __next__ 等价于 next()

    5、迭代器取值

    迭代器取值特点:

      a、前面提到过迭代器取值只能通过__next__方法。每执行一次就提取一行内容,若容器中没有可取值会报错:StopIteration

      b、只能往后一次取,不能后退。

    注意:文件对象及是可迭代对象又是迭代器对象

    f1 = open('xxx.txt','r',encoding='utf-8')
    # 调用f1内置的__iter__方法
    # iter_f = f1.__iter__()
    # print(iter_f is f1)

    由以上代码可知:文件对象f 调用 __iter__方法得到是自己本身。

    提出问题:为什么文件对象是迭代器对象还会有__iter__方法?

    解决问题--引出:for循环原理 --  for 循环后面的in 若接的是迭代器对象,但迭代器对象没有__iter__方法的话会for循环会报错!

    得出结论如下:

      迭代器对象无论执行哪个多少次__iter__方法都是得到迭代器对象自己本身。(******)

    6、总结:

      可迭代对象内置只有__iter__方法;

      迭代器对象既有__iter__方法,也有__next__方法;

      迭代器对象一定是可迭代对象,但可迭代对象不一定是迭代器对象。

    二、for 循环内部原理

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

    for 循环内部的本质:

      1、将 in 后面的对象通过 调用__iter__方法转成迭代器对象;

      2、调用__next__方法迭代取值;

      3、一直迭代取值,直到容器为空,报错。然后捕获异常StopIteration,当 __next__方法报错,自动结束循环。

    注意:由上可知,for循环后 in对应的对象是可迭代对象

    迭代取值的优缺点:

      优点:1、不依赖索引取值;

         2、内存中永远只出现一行内容,不会导致内存溢出的情况出现。

      缺点:1、不能指定取值;

         2、当取值为空时,会报出StopIteration 的错误。

    三、生成器

    1、生成器:

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

    def func():
        print('first')
        yield  666  # 函数内如果有yield关键字,那么加括号执行函数的时候并不会触发函数体代码的运行
        print('second')
        yield  777
        print('third')
        yield  888
        print('forth')
        yield
        yield
    # yield后面跟的值就是调用迭代器__next__方法你能得到的值
    # yield既可以返回一个值也可以返回多个值 并且多个值也是按照元组的形式返回
    g = func()  # 生成器初始化:将函数变成迭代器

    2、自定义迭代器完成range()方法

    def my_range(start,end,step=1):
        while start < end:
            yield start
            start += step
    
    for j in my_range(1,100,2):
        print(j)

    3、生成器表达式  -- 就是元组括号:例如:res = (i  for i in range(5))  得到生成器对象。

    res3 = range(10)
    print(res3)  # range(0, 10)
    
    res2 = [i for i in range(10)]
    print(res2)  # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    
    res = (i for i in range(10))
    print(res)  # <generator object <genexpr> at 0x01A2D0F0> 得到一个生成器对象
    print(res.__next__())  # 0
    print(res.__next__())  # 1
    """
    由上可知:
        生成器不会主动执行任何一行代码
        必须通过__next__触发代码的运行
    """

    4、yeild 关键字的特点、与return的区别等

    特点:1、返回值与return一样可以返回一个值,也可以返回多个值,多个值以元组形式返回;

          2、暂存函数的运行状态,

         3、可以通过外接传参 (前提是代码运行到yeild的位置,才可以通过send方法传参)

         args = yeild 111

        send方法通过外界传参之后会自动运行下一句代码。

     区别:yeild 可以执行多次,return执行一次之后函数就会结束。

    5、重点!!!面试题~

     解题思路:

    四、常用的内置函数

    abs() 求绝对值

    # abs 求绝对值
    print(abs(-1.11))  # 1.11

    all() any() 返回布尔值

    # all() any() 返回布尔值
    li = [0,2,34,5]
    print(all(li))  # False  容器里面的元素全为True才返回True
    print(any(li))  # True   容器里面只要有一个元素为True 就返回True

    globals()  locals()

    def func():
        user_name = '我是局部名称空间'
        print(locals())  # 返回当前位置所存储的名称空间的名字  {'user_name': '我是局部名称空间'}
        print(globals())  # 无论在什么位置,返回的都是全局名称空间的名字
    func()

    bin() oct() hex() 十进制转其他进制, int('其他进制字符',进制数) 其他进制转十进制

    bytes() 字符编码转换的两种形式

    # bytes() 字符编码转换两种方式
    x = '上海'
    print(x.encode('utf-8'))
    print(bytes(x,encoding='utf-8'))

    callable()

    # callable() 是否可调用...
    list2 = [1,2,3,4]
    def index():
        pass
    print(callable(list2))  # False
    print(callable(index))  # True

    chr()  ord()   ASCII码表对应字符与数字的转换

    # chr() ord()  ASCII码表对应字符与数字的转换
    print(chr(97))  # a  将ascii码表对应数字转为字符
    print(ord('a'))  # 97  将ASCII码表对应字符转为数字

    dir() 获取当前名称空间里的名字    /  主要用于模块中名称空间名字的查找

    # dir() 获取当前名称空间里的名字  /主要用于模块中名字变量的查找
    list3 = [23,34,45,66]
    print(dir(list3))  # 好多。。。

    divmod() 分页器

    # divmod() 分页器
    print(divmod(121,10))  # (12, 1) 返回整除数和余数
    # 网站分页的实现:
    num1, num2 = divmod(121,10)
    if num2:
        num1 += 1
    print('当前需要的页数为:%s'%num1)  # 当前需要的页数为:13

    enumerate() 枚举

    # enumerate() 枚举
    list3 = ['jason','tank','egon']
    for i ,j in enumerate(list3):
        print(i,j,end=' ')  # 0 jason 1 tank 2 egon 默认索引从0开始
    for i ,j in enumerate(list3,1):
        print(i,j,end=' ')  # 1 jason 2 tank 3 egon  设置索引从1开始

    eval()   exec()   可以执行字符串内的代码

    # eval() exec()
    str1 = """
    print('hello world')  # 注意:要顶格对齐!!!
    x = 1
    y = 2
    print(x+y)
    """
    #eval(str1)  # 报错! eval()只能运行简单的代码,不能进行逻辑运算
    exec(str1)  # hello world  3
    # eval()需要注意的示例
    name = 'jason'
    s2 = """
    name
    """
    print(eval(s2))  # jason

    format() 格式化输出,三种玩法

      和%s一样{}占位,{index}索引,{name}指名道姓即关键字传参

    isinstance() 判断对象是否属于某种数据类型   /  推荐使该方法

    # isinstance()
    n = 'adads'
    print(isinstance(n,str))  # True
    print(isinstance(n,dict))  # False

    pow()    幂次方相乘

    # pow()
    print(pow(3,2))  # 9   3的平方

    round()   四舍五入进位整数

    # round()
    print(round(3.49))  # 3
    print(round(3.51))  # 4
  • 相关阅读:
    高精度模板(未完待续)
    $CH0201$ 费解的开关
    $POJ2288$ $Islands$ $and$ $Bridges$
    luoguP1445 [Violet]樱花
    P3694 邦邦的大合唱站队
    [NOI2009]管道取珠
    [AHOI2006]基因匹配
    luogu P3411 序列变换
    HNOI2001 产品加工
    牛客ACM赛 B [小a的旅行计划 ]
  • 原文地址:https://www.cnblogs.com/qinsungui921112/p/11190267.html
Copyright © 2011-2022 走看看