- 列表生成式
array = [i*2 for i in range(10)]
=>[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
#相当于
a = []
for i in range(10):
a.append(i*2)
#假设func存在
[ func(i) for i in range(10)]
- 生成器
1.什么事生成器
通过列表生成式,可以直接创建一个列表。由于内存的限制,列表的容量有限。如果列表元素过多,会占用很多的空间,如果仅仅只需要个别列表元素,那么后面绝大多数元素占用的空间会白白浪费。所以这时候我们就需要用到生成器(generator)
import time
def timer(funcType):
def out_wrapper(func):
def wrapper(*args, **kwargs):
start = time.time()
func(*args, **kwargs)
end = time.time()
print(funcType,":%s" % (end - start))
return wrapper
return out_wrapper
#没有使用生成器
@timer(funcType="Normal")
def func_normal():
a = [i for i in range(50000000)]
# 生成器
@timer(funcType="Generator")
def func_generator():
a = (i for i in range(50000000))
print(a)
func_normal()
func_generator()
=> Normal :4.411223411560059
<generator object func_generator.<locals>.<genexpr> at 0x000001E9CC7F5CA8>
Generator :0.0
由于5千万个元素过大,我们列表中的元素不打印了。当我们打印生成器的时候发现,生成器仅仅只是声明了一块地址,并没有生成列表。
生成器只在访问他的时候才会生成数据。而且生成器值记录当前的位置,并不会记录之前的位置,想要的得到下一个值我们用next()方法。
a = (i for i in range(5))#[0,1,2,3,4]
a.__next__()
a.__next__()
print(a.__next__()) #2
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
我们要将函数fib变为generator只需要将fib中的print改为yield。
def fib(max):
n, a, b = 0, 0, 1
while n < max:
yield b
a,b = b, a+b
n = n+1
print(fib(100))
f = fib(100)
f.__next__()
print("do something")
f.__next__()
print(f.__next__())
=> <generator object fib at 0x000001E958E25CA8>
print("do something")
2
使用生成器时,可以在函数运行过程中做其他事情。
3.生成器并行
使用生产者消费者模型解释生成器并行:
import time
def consumer(name):
print("%s 我准备吃饭了" %(name))
while True:
yield = food
print("[%s]吃了菜品[%s]!" %(name,food))
def producer():
custom1 = consumer("Custom1")
custom2 = consumer("Custom2")
custom1.__next__()
custom2.__next__()
for i in range(10):
time.sleep(1)
print("做了一道菜")
custom1.send(i)
custom2.send(i)
producer()
在这里生成器相当于C#中的ansy方法。方法send(i)相当于将参数传递给yield所指变量。