列表生成式:
[i*2 for i in range(10)]
生成[0,2,4,6,8,10,12,14,16,18]
注:列表生成式可以直接生成列表,但是当数据量特别大的时候,会特别占内存,而且不需要的内容也会占用到空间。
生成器:节省内存空间,只有在调用到的时候才会生成数据
节省内存方式:只记录当前的数据位置,之前的数据会释放。只有一个next方法:_next_()
要创建一个generator,有很多种方法。第一种方法只要把一个列表生成式的[]改成(),就创建了一个generator:
eg:
a=[ i * i for i in range(10)]
print(a)
b=( i * i for i in range(10))
print(b)
输出:
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
<generator object <genexpr>> at 0x02126240>>
eg:输出斐波那契数列的前N个数:
函数方法:
def fib(max):
n, a, b = 0, 0, 1
while n < max:
print(b)
a, b = b, a + b
'''t = (b, a + b) # t是一个tuple
a = t[0]
b = t[1]'''
n = n + 1
return 'done'
fib(5)
生成器方法:
def fib(max):
n,a,b = 0,0,1
while n < max:
#print(b)
yield b
a,b = b,a+b
n += 1
return '-----done-----'#功能是异常时打印消息
f=fib(5)
print(f)
输出:<generator object fib at 0x02126210>>
print(f.__next__()) #逐行执行并打印
print(f.__next__())
print("干点别的事")
print(f.__next__())
输出:
1
1
干点别的事
2
注:
1.generator和函数的执行流程不一样。函数是顺序执行,遇到return语句或者最后一行函数语句就返回。而变成generator的函数,在每次调用next()的时候执行,遇到yield语句返回,再次执行时从上次返回的yield语句处继续执行。
2.在循环过程中不断调用yield,就会不断中断。把函数改成generator后,我们基本上不会用next()来获取下一个返回值,而是直接使用for循环:
for n in fib(6):
print(n)
用for循环调用generator时,发现拿不到generator的return语句的返回值。如果想要拿到返回值,必须捕获StopIteration错误,返回值包含在StopIteration的value中:
def fib(max):
n,a,b = 0,0,1
while n < max:
#print(b)
yield b
a,b = b,a+b
n += 1
return '-----done-----'
f=fib(5)
g = fib(6)
while True:
try:
x = next(g)
print('g:', x)
except StopIteration as e:
print('Generator return value:', e.value)
break
输出:
g: 1
g: 1
g: 2
g: 3
g: 5
g: 8
Generator return value: -----done-----