zoukankan      html  css  js  c++  java
  • 迭代器、for循环本质、生成器、常用内置方法整理

    迭代器

      什么是迭代器

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

        迭代器:迭代取值的工具

      为什么要用迭代器

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

    重复+每次迭代都是基于上一次的结果而来的

    l = [1, 2, 3, 4]
    s = 'hello'
    n = 0
    while n < len(s):
        print(s(n))
        n+=1

      根据我们知道的数据类型中,其中 字符串(str)、列表(list)、元组(tuple)、字典(dict)、集合(set)、文件对象 都属于需要迭代取值的数据类型,内置有__iter__方法的都叫做可迭代对象

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

    迭代器对象

      1.内置有__iter__方法

      2.内置有__next__方法

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

    列表取值

    l = [1,2,3,4]
    iter_l = l.__iter__()  #生成一个迭代器对象
    
    
    #迭代器取值,调用__next__方法
    print(iter_l.__next__())  #取值:1
    print(iter_l.__next__())  #取值:2 
    print(iter_l.__next__())  #取值:3
    print(iter_l.__next__())  #取值:4
    print(iter_l.__next__())  #当列表中的值被取完时,直接报错StopIteration

    字典取值

    d = {'name':'zhangsan', 'password':'123', 'hobby':'study'}
    
    #将可迭代对象d转换成迭代器对象
    iter_d = d.__iter__()
    
    #迭代器对象取值,使用__next__
    print(iter_d.__next__())   #取值:name
    print(iter_d.__next__())   #取值:password
    print(iter_d.__next__())   #取值:hobby
    print(iter_d.__next__())   #当字典中的key被取完时,直接报错StopIteration

    在项目过程中,所有的程序肯定是不允许有报错信息的,这时我们可以使用捕获异常来处理

    while True:
        try:
            print(iter_d.__next__())
        except StopIteration:    #放入程序的报错信息
            print('值已经被取完了')
            break

    ps:迭代器取值的特点:只能从前往后依次取,不能倒序

    for循环内部的本质

    for循环内部的本质

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

      2.调用__next__迭代取值

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

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

    小示例:

    #使用匿名函数,以及map方法求取出的值
    
    l = [1,2,3,4]
    res = map(lambda x:x+1,l)
    print(map(lambda x:x+1,l))
    print(res.__next__())
    print(res.__next__())
    print(res.__next__())
    print(res.__next__())
    
    #打印结果 
    2
    3
    4
    5

    小结:

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

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

    迭代取值:

      优点:

        1.不依赖于索引取值

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

      缺点:

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

        2.取完之后会报错StopIteration

    生成器

    生成器:用户自定义的迭代器

    def func():
        print('first')
        yield  666  # 函数内如果有yield关键字,那么加括号执行函数的时候并不会触发函数体代码的运行
        print('second')
        yield  777
        print('third')
        yield  888,999
        print('forth')
        yield 
    g = func()  # 生成器初始化:将函数变成迭代器
    print(g)
    print(g.__next__())
    print(g.__next__())
    print(g.__next__())
    打印结果:

    <generator object func at 0x000001F4D0F73780>
    first
    666
    second
    777
    third
    (888, 999)

    # yield后面跟的值就是调用迭代器__next__方法能得到的值

    # yield既可以返回一个值,也可以返回多个值,并且多个值也是按照元组的形式返回

    小练习:

    有这样一个例子,如何把它写成一个生成器呢?

    for i in range(1,10,2):
      print(i)

    def my_range(start,end,step=2):   # 定义三个形参
        while start < end:                     
            yield start    # 返回start的值
            start += step     #每次循环start都加上step的值
    for j in my_range(1,10,2):
        print(j)
    View Code

    yield的用法

    yield支持外界为其传参

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

    小结:

    yield:

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

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

      3.可以返回值

    与return之间异同点

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

      不同点:

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

        2.yield还可以接收外部传入的值

    生成器生成式

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

    with open('xxx.txt','r',encoding='utf-8') as f:
        g = (len(line) for line in f)
        print(sum(g))    #求和

    练习

    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)
    print(res)
    
    res的结果是多少

    答案

    [20,21,22,23]
    View Code

    内置方法

    abs:绝对值

    print(abs(-11.11))  # 求绝对值
    l = [0,1,0]
    print(all(l))  # 只要有一个为False就返回False
    print(any(l))  # 只要有一个位True就返回True

     callable :可调用的(可调用返回True,不可调用返回False)

    l = [1,2,3]
    def index():
        pass
    print(callable(l))
    print(callable(index))
    # print(chr(97))  # 将数字转换成ascii码表对应的字符
    # print(ord('a'))  # 将字符按照ascii表转成对应的数字

    dir:获取当前对象名称空间里面的名字

    l = [1,2,3]
    print(dir(l))

    divmod:分页器

    print(divmod(101,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

    s = """
    print('hello baby~')
    """
    eval(s)
    
    # 打印结果
    hello  baby~



    s1 = """
    print(1 + 2)
    for i in range(10):
    print(i)
    """
    eval(s1)

    # 报错:SyntaxError: invalid syntax

    # eval不支持逻辑代码,只支持一些简单的python代码

    exec

    s1 = """
    print(1 + 2)
    for i in range(10):
        print(i)
    """
    exec(s1)

    # 打印结果
    1
    2
    3
    4
    5
    6
    7
    8
    9

    format 三种玩法
      {}占位
      {index} 索引
      {name} 指名道姓

    isinstance:判断是否属于某个数据类型

    n = 1
    print(type(n))
    print(isinstance(n,int))
    
    
    # 打印结果
    <class 'int'>
    True
    print(pow(2,3))   #2的三次方
    
    # 打印结果
    8
    print(round(3.4))  #四舍五入
    
    # 打印结果
    3

    help:打印函数注释

    def login():
        """
        一起嗨皮
        :return:
        """
    print(help(login))
  • 相关阅读:
    MySQL 批量删除相同前缀的表
    MySQL 命令登录
    MySQL 密码修改
    谷歌浏览器开发者工具截图
    VIM命令图解
    基于环境变量为多用户配置不同的JDK(win)
    Reddit: 只有独生子女才明白的事
    JSONObject与null
    SpringFramework中重定向
    XML修改节点值
  • 原文地址:https://www.cnblogs.com/chengzige/p/11190559.html
Copyright © 2011-2022 走看看