引引言引言言
引言:列表生成式
[i**2 for i in range(10)]
此外,列表生成时也可以加入函数:
def func(x):
return x**2
list = [func(x) for x in range(10)]
生成器:
生成器的两种构建方式:一是通过小括号(),一是通过yield关键字。这里yield相当于return,不同之处在于yield结束后会保存此时函数的状态。
第一种方式:小括号
gene = (x**2 for x in range(10))
print gene
<generator object <genexpr> at 0x000000000287DB88>
生成器对象的特点:
1:在你用到数据的时候,会给你生成,从而节省内存空间
2:不能跳跃取值,即只能顺序的生成值,
3:生成器是可迭代对象(后面会讲到什么是可迭代对象)
gene = (x**2 for x in range(5))
first_num = next(gene)
second_num = next(gene)
third_num = next(gene)
print first_num,second_num,third_num
0 1 4
通过生成器对象取值,推荐使用的方法是next()。使用方式:next(生成器对象)。当超过迭代范围时,会抛出迭代异常,停止迭代。除了next(),还可以使用for进行数据生成。
gene = (x**2 for x in range(4))
for i in gene:
print i
0
1
4
9
这里面for内部做了两件事:1:执行next方法;2:处理stopIteration异常
第二种方式:yield关键字:构建出生成器函数。调用该函数,得到生成器对象,然后用前面提到的方法next()或者for循环可以进行数据生成。
def fun():
gene = (x ** 2 for x in range(4))
for i in gene:
yield i
res = fun()
print(next(res))
print(next(res))
print(next(res))
0
1
4
生成器对象还有一个方法send(),功能与next()差不多。只不过send()方法可以传递参数。传递的参数会赋值给上一次被挂起的yield语句的返回值。value = yield 1。这里需要注意:第一次send前如果没有next,只能执行send(None)。
def MyGenerator():
value = (yield 1)
value = (yield value)
gen = MyGenerator()
print gen.next()
print gen.send(2)
print gen.send(3)
上面代码的运行过程如下:
1、当调用gen.next()方法时,python首先会执行MyGenerator方法的yield 1语句。由于是一个yield语句,因此方法的执行过程被挂起,而next方法返回值为yield关键字后面表达式的值,即为1。
2、当调用gen.send(2)方法时,python首先恢复MyGenerator方法的运行环境。同时,将表达式(yield 1)的返回值定义为send方法参数的值,即为2。这样,接下来value=(yield 1)这一赋值语句会将value的值置为2。继续运行会遇到yield value语句。因此,MyGenerator方法再次被挂起。同时,send方法的返回值为yield关键字后面表达式的值,也即value的值,为2。
3、当调用gen.send(3)方法时,将表达式(yield value)的返回值定义为send方法参数的值,即为3。这样,接下来value=(yield value)这一赋值语句会将value的值置为3。继续运行,MyGenerator方法执行完毕,故而抛出StopIteration异常。
需要注意,在一个生成器对象没有执行next方法之前,由于没有yield语句被挂起,所以执行send方法会报错。