列表特性:列表是一次性生成的
a = [1,2,3,4,5,6,7,8,9]
或
[ i*2 for i in range(10)] ###--->列表生成式
===[2,4,6,8,10,12,14,16,18,20]===
两个列表的区别:
1列表是写死的,2列表可以里面做一些操作把相应的东西输出出来
列表生成式目的是为了使代码更简洁,且可以实现更复杂的功能,如将i的值传至函数中
[fun(i) for i in range(10)]
生成式:通过生成式可以直接创建一个列表,但受内存大小的限制,列表的容量是有限的,而且创建一个大数据量的列表,不仅占用的内存空间很大,而且如果仅访问前面几个元素,那么后面的元素所占用的空间都浪费掉了。
所以,如果列表可以按照某种算法推算出来,我们可以在循环的过程中推断出后续需要的列表元素而不需要创建完整的列表,从而大大节省了内存空间。在python中这种一边循环了边推算下一个列表元素的方式称之为生成器:generator
创建一个generator有很多方法,第一种简单的方法为把列表生成式的[]修改为(),就创建了一个generator
[ i*2 for i in range(10)] ###--->列表生成式
==结果===[2,4,6,8,10,12,14,16,18,20]===
( i*2 for i in range(10)) ###--->generator
==结果===<generator object <genexpr> at 0x1022ef630>===
generator是每调用一次则生成一个元素,若没调用则不生成后面的元素,从而节省内存空间
例:
g = ( i*2 for i in range(10))
print(g.__next__())
print(g.__next__())
print('********')
print(g.__next__())
==结果===
0
2
********
4
它只有__next__()方法,没有其他方法,它不能被切片,如想取第3个值g(2)是不行的
以上方式也可以用循环的方式去调用它
如斐波那契数列,除第一个数外,任意一个数都是由前面两个数相加得到:
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'
fib(100)
注意:
a,b= b,a+b
并非是
a = b
b = a+b
这么简单的事情
它应该是
t (b,a+b)
a = t[0]
b = t[1]
但不必显示地写出t变量就可进行赋值
而如果需要把上面的这个函数变成一个生成器,那么只需要修改一个代码
def fib(max):
n,a,b=0,0,1
while n < max:
yield b
a,b= b,a+b
n = n+1
return 'done'
print(fib(100))
==结果===<generator object fib at 0x1022ef630>===
那需要需要输出里面的内容呢!操作如下
f = fib(100)
print(f.__next__())
print(f.__next__())
那如果前面有几个next的时候,再用for去循环它的时候,那么它是从中间开始输出生成的
假如next的数量超出生成器的范围的时候,会抛出StopIteration异常,就需要异常捕捉,如上面的函数
def fib(max):
n,a,b=0,0,1
while n < max:
yield b #函数中断的位置,调用next时返回这个位置
a,b= b,a+b
n = n+1
return 'done'
g = fib(10)
while True:
try:
x = next(g) #内置方法,与__next
print('g:',x)
except StopIteration as e:
print('Generator return value:',e.value)
break
转载于:https://blog.51cto.com/daring/1887942