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
原文地址:https://www.cnblogs.com/kumunotes/p/10589935.html