列表生成式
需求:循环0-10,把其中每个值加一并打印
# 文艺青年版 n = list(range(10)) for index, i in enumerate(n): n[i] += 1 print(n) [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] # 执行结果 # 装逼青年版 n = list(range(10)) print(list(map(lambda x:x+1, n))) [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] # 执行结果 # 更加装逼青年版(列表生成式) n = [i+1 for i in range(10)] print(n) [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] # 执行结果
列表生成式作用就是在一行内实现对列表的操作,其中 a 可以放任何东西,如字符串, 字典,元祖等 , i可以进行普通运算,也可以进行三元运算,比如,实现i< 5, 什么也不干,如果i >5, 自己乘自己
n = list(range(10)) a = [i if i < 5 else i*i for i in n] print(a) [0, 1, 2, 3, 4, 25, 36, 49, 64, 81] #执行结果
n = 'alex' n = [i for i in range(10)] print(n) ['a', 'l', 'e', 'x'] # 执行结果
生成器
生成器特点:
1.要什么不会立即产生,只能一个一个产
2.只能往前走,不能回退
3.走到最后一步的时候,就会报错
根据上面的需求,以个列表生成器可以生成一个列表,但是列表的容量是有限的,因为受到内存的限制。
如果我要创建一个包含100w元素的列表,他占用的内存很大,而且如果我只需要访问前面的一些元素,那后面的就白创建了。也就是创建好了列表取值的同时,不是知道什么时候停,这个方法是直接创建一个100w数据的列表,然后取的时候一个一个取,这种低效浪费空间。现在有个需求,就是满足我取到着100w个数据而且省空间,就可以先生成一个1,然后下次调用的时候生成2,依次类推,这样不涉及列表的切片操作,也就是说再调用数据之前,不会一次生成100w的数据,但知道数据的规律,知道要什么数据,然后一个一个往上加,就是取得时候直接调用一个公式,每取一次数据加1.
举例:
我现在有一个工厂,要给用户提供100w个杯子,用户给你提供了10%的预付款,你不能就一下子给他产了100w个,要是他只要了1000个,就倒闭了,那你就凉凉了。所以第一种方案可以让他要几个你生产几个,也就是边取边生产,这样的话你就不会有库存,放到计算机里边就是不占用内存空间了。这种方法就是生产能力,放到这里就是这种方法,这种方法需要提前定义好,再python中,这种一边循环一边计算的方法就是生成器:generator
#原来,列表生成式里是这么写的 a = [i for i in range(5)] print(a) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] # 执行结果 # 现在 a = (i for i in range(10)) print(a) <generator object <genexpr> at 0x0000023520717C50> # 执行结果 # 生产10个数据的算法已经存到a里边了,也就是说a有生产能力了 #调用 next(a) 0 next(a) 1 next(a) 2 # 这里边是由序号的
如果生产到一半,用户不要了,那么因为你的算法已经有了。所以直接调就可以了
a <generator object <genexpr> at 0x0000023520717C50> next(a) 3
但是只能一直往前走,就是往前一直加1,走到最后就会报错
next(a) 4 next(a) Traceback (most recent call last): File "<stdin>", line 1, in <module> StopIteration #可以理解成停止生产
生成器的两种创建方式:
1.列表生成式()
2.函数()
区别:列表生成式最多只能生成一个复杂的三元运算,涉及到比较复杂的,只能用函数
举例 : 如果你要打开一个用函数定义好的文件,不能做到先读一部分然后处理完再读一部分,这样用生成器就可以实现,其实在学文件操作的时候,for循环文件一行一行的读就是生成器