1、列表是写死的,固定的。
a=[0,1,2,3,4,5,6,7,8,9]
print(a)
2、列表生成式会使代码更加简洁
a=[]
for i in range(10):
a.append(i*3)
print(a)
3、列表与列表生成式的运行结果如下:
列表运行结果:[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
列表生成式运行结果:[0, 3, 6, 9, 12, 15, 18, 21, 24, 27]
什么是生成器
通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。
所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间。在Python中,这种一边循环一边计算的机制,称为生成器:generator。
如何创建一个生成器
在一个一般函数中使用yield关键字,可以实现一个最简单的生成器,此时这个函数变成一个生成器函数。yield与return返回相同的值,区别在于return返回后,函数状态终止,而yield会保存当前函数的执行状态,在返回后,函数又回到之前保存的状态继续执行。
生成器函数与一般函数的不同
生成器函数包含一个或者多个yield当调用生成器函数时,函数将返回一个对象,但是不会立刻向下执行像__iter__()和__next__()方法等是自动实现的,所以我们可以通过next()方法对对象进行迭代一旦函数被yield,函数会暂停,控制权返回调用者局部变量和它们的状态会被保存,直到下一次调用函数终止的时候,StopIteraion会被自动抛出生成器如何节省资源?
只记住当前位置,生成器只保留一个值,next之后上一个值就没有了
只有一个next方法,
#b#__next__()
著名的斐波那契数列
著名的斐波那契数列,除第一个和第二个数外,任意一个数都可由前两个数相加得到:
1,1,2,3,5,8,13,21,34,...
斐波那契数列用列表生成式写不出来,但是,用函数把它打印出来却很容易:
def fib(max): n,a,b=0,0,1 while n<max: print(b) a, b = b, a+b n=n+1 return 'done'f=fib(10)运行结果:
1
1
2
3
5
8
13
21
34
55
想要使它变为生成器,只需要将print(b),改为yiled b即可
def fib(max): n,a,b=0,0,1 while n<max: # print(b) yield b a, b = b, a+b #a = b a = 1,b=2, a=b, a=2 #b = a+b b=2+2=4 n=n+1 return 'done'#异常时打印的消息运行结果:通过使用next的方式进行取值
print(f.__next__())
print(f.__next__())
print(f.__next__())
print(f.__next__())
print(f.__next__())
print(f.__next__())
print(f.__next__())
print(f.__next__())
print(f.__next__())
print(f.__next__())
print(f.__next__())
使用for循环那个return的down是无法打印的
for i in f:
print(i)
使用next方法取数据取不出来了,就会抛出一个异常
Traceback (most recent call last):
File "D:\python\index.py", line 85, in <module>
print(f.__next__())
StopIteration: done
如何处理异常,可通过抓取异常
g=fib(6)
#异常处理代码
while True:
try:
x = next(g)
print('g:', x)
except StopIteration as e:
print('Generator return value:', e.value)
最终运行结果:
g: 1
g: 1
g: 2
g: 3
g: 5
g: 8
Generator return value: done
===start loop===
为什么使用生成器
更容易使用,代码量较小内存使用更加高效。比如列表是在建立的时候就分配所有的内存空间,而生成器仅仅是需要的时候才使用,更像一个记录代表了一个无限的流。如果我们要读取并使用的内容远远超过内存,但是需要对所有的流中的内容进行处理,那么生成器是一个很好的选择,比如可以让生成器返回当前的处理状态,由于它可以保存状态,那么下一次直接处理即可。流水线生成器。假设我们有一个快餐记录,这个记录的地4行记录了过去五年每小时售出的食品数量,并且我们要把所有的数量加在一起,求解过去5年的售出的总数。假设所有的数据都是字符串,并且不可用的数字被标记成N/A。那么可以使用下面的方式处理:结语
感谢阅读,欢迎在评论区中发表自己不同的观点,若有其他问题请在评论区留言,喜欢的朋友请多多关注转发支持一下。