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__()

著名的斐波那契数列

python 生成器和迭代器-LMLPHP

著名的斐波那契数列,除第一个和第二个数外,任意一个数都可由前两个数相加得到:

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。那么可以使用下面的方式处理:结语

感谢阅读,欢迎在评论区中发表自己不同的观点,若有其他问题请在评论区留言,喜欢的朋友请多多关注转发支持一下。

10-07 07:21