zoukankan      html  css  js  c++  java
  • python列表生成式、生成器,迭代器与二分法

    一、列表生成式

    • 列表生成式是快速生成一个列表的一些公式
    • 列表生成式的书写格式:[x*x for x in range(1 , 11)]
    • 列表生成式语法是固定的,[]里面for 前面是对列表里面数据的运算操作,后面跟平常for循序一样遍历去读取。运行后会自动生成新的列表
    一般列表生成式
    list1 = list(range(1,10))           #不使用列表生成式生成列表
    list2 = [x for x in range(1,10)]    #使用列表生成式生成列表
    print(list1)
    print(list2)
    
    运行结果:
    [1, 2, 3, 4, 5, 6, 7, 8, 9]
    [1, 2, 3, 4, 5, 6, 7, 8, 9]
    
    
    带过滤功能的列表生成式
    L = [3, 7, 11, 14,19, 33, 26, 57, 99] 
    # 不使用列表生成式实现 
    list5 = [] 
    for x in L: 
        if x < 20: 
        list5.append(x) 
    # 使用列表生成式实现 
    list6 = [x for x in L if x > 20]
    示例

    二、生成器

    把列表推导式的[]换成()就是生成器表达式

    1. 生成器的执行过程与特性

    生成器的执行过程:

    在执行过程中,遇到yield关键字就会中断执行,下次调用则继续从上次中断的位置继续执行。

    生成器的特性:

    • 只有在调用时才会生成相应的数据
    • 只记录当前的位置
    • 只能next,不能prev

    2. 生成器的调用方式

    要调用生成器产生新的元素,有两种方式:
    • 调用内置的next()方法
    • 使用循环对生成器对象进行遍历(推荐)
    • 调用生成器对象的send()方法

    使用next()方法遍历生成器

    list = (i for i in range(1,10))
    print(list)
    print(next(list))
    print(next(list))

    使用循环遍历生成器

    list = (i for i in range(1,10))
    for x in list:
        print(x)

    调用生成器对象的send()方法

    def my_range(start,end):
        for i in range(start,end):
            ret = yield 2*i +1
            print(ret)
    res = my_range(2,5)
    print(res.send(None))
    print(res.send('hello'))
    
    运行结果:
    5
    hello
    7

    注意:

    • next()会调用yield,但不给它传值
    • send()会调用yield,也会给它传值(该值将成为当前yield表达式的结果值)
    需要注意的是:第一次调用生成器的send()方法时,参数只能为None,否则会抛出异常。当然也可以在调用send()方法之前先调用一次next()方法,目的是让生成器先进入yield表达式。

    三、可迭代对象

    可直接用于for循环的对象统称为可迭代对象(Iterable)。
    目前我们已经知道的可迭代(可用于for循环)的数据类型有:
    • 集合数据类型:如list、tuple、dict、set、str等
    • 生成器(Generator)
    可以使用isinstance()来判断一个对象是否是Iterable对象:
    from collections import Iterable 
    print(isinstance([], Iterable))
    

      

    四、迭代器(Iterator)

    1. 迭代器的定义

    可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator。
    很明显上面讲的生成器也是迭代器。当然,我们可以使用isinstance()来验证一下:
    from collections import Iteratorprint(isinstance((x for x in range(5)), Iterator))

     输出结果为:True

    2. 对迭代器的理解

    实际上,Python中的Iterator对象表示的是一个数据流,Iterator可以被next()函数调用被不断返回下一个数据,直到没有数据可以返回时抛出StopIteration异常错误。可以把这个数据流看做一个有序序列,但我们无法提前知道这个序列的长度。同时,Iterator的计算是惰性的,只有通过next()函数时才会计算并返回下一个数据。
    生成器也是这样的,因为生成器也是迭代器。

    五、Iterable、Iterator与Generator之间的关系

    • 生成器对象既是可迭代对象,也是迭代器: 我们已经知道,生成器不但可以作用与for循环,还可以被next()函数不断调用并返回下一个值,直到最后抛出StopIteration错误表示无法继续返回下一个值了。也就是说,生成器同时满足可迭代对象和迭代器的定义;
    • 迭代器对象一定是可迭代对象,反之则不一定: 例如list、dict、str等集合数据类型是可迭代对象,但不是迭代器,但是它们可以通过iter()函数生成一个迭代器对象。
    也就是说:迭代器、生成器和可迭代对象都可以用for循环去迭代,生成器和迭代器还可以被next()方函数调用并返回下一个值。

    六、递归与二分法

    递归调用是函数嵌套调用的一种特殊形式,函数在调用时,直接或间接调用了自身,就是递归调用。
    #直接调用本身def f1():
        print('from f1')
        f1()
    f1()
    #间接调用本身def f1():
        print('from f1')
        f2()
    def f2():
        print('from f2')
        f1()
    f1()
    # 调用函数会产生局部的名称空间,占用内存,因为上述这种调用会无需调用本身,python解释器的内存管理机制为了防止其无限制占用内存,对函数的递归调用做了最大的层级限制

     二分法

    l=[1,2,10,30,33,99,101,200,301,311,402,403,500,900,1000] #从小到大排列的数字列表
    def search(n,l):
        print(l)
        if len(l) == 0:
            print('not exists')
            return
        mid_index=len(l) // 2
        if n > l[mid_index]:
            #in the right
            l=l[mid_index+1:]
            search(n,l)
        elif n < l[mid_index]:
            #in the left
            l=l[:mid_index]
            search(n,l)
        else:
            print('find it')
    
    
    search(3,l)
    实现类似于in的效果
    View Code
  • 相关阅读:
    Dev中出现Error 0: 操作成功完成。
    找出一个二维数组中的鞍点,即该位置上的元素在该行上最大、在该列上最小。也可能没有没有鞍点。
    oracle 日常删除多余数据
    java程序练习:输入数字转换成中文输出(金额相关)
    linux压缩和解压文件命令
    一篇文章搞定Git——Git代码管理及使用规范
    读书心得(1)-20191108
    回表查询的说明
    Java 8新特性解读
    java-try catch中return在finally之前 还是之后执行
  • 原文地址:https://www.cnblogs.com/kumunotes/p/10589935.html
Copyright © 2011-2022 走看看