生成器
生成器可以理解为一种数据类型,这种数据类型自动实习了迭代器协议(其他的数据类型需要调用自己内置的_iter_()方法),所以生成器就是迭代对象;
生成器解析,对于我们的列表解析来说,只需要简单的包中括号更换成小括号就可以了,它是按需计算的或者说的延迟计算的;
生成器分类及在Python中的表现形式
1、生成器函数:常规函数定义,但是,使用yield语句而不是return语句返回结果,yield语句一次返回一个结果,在每个结果中间,挂起函数的状态,以便下次从这个位置继续往下执行;
2、生成器表达式:类似于列表推导,但是生成器返回按需产生结果一个对象,而不是一次构建一个结果列表;
生成器是一个迭代器,所以我们可以使用next来使用
生成器函数示例:
>>> def gen():
... while True:
... yield 0
... print('...')
...
>>> g=gen()
>>> next(g)
0
>>> next(g)
...
0
生成器的定义和函数类似,但是有yield语句,生成器执行到yield的时候会暂停,在此next会从暂停的地方继续执行
yield弹出值,暂停函数,return返回值,结束函数。
两者是可以一起使用的,并且return也可以结束我们的函数
>>> def gen(x):
... for i in range(10):
... if i == 3:
... return i
... yield i
...
>>> g = gen(10)
>>> for x in g:
... print(x)
...
0
1
2
生成器的计数器的实现
>>> def connt(init):
... c=init
... while True:
... yield c
... c+=1
...
>>> c=connt(0)
>>> next(c)
0
>>> next(c)
1
或
#!/usr/bin/env python
#
i=1
def test(i):
while True:
yield i
i+=1
t=test(i)
for i in t:
print(i)
生成器的阶乘的实现
>>> def fac():
... ret =1
... idx =1
... while True:
... yield ret
... idx +=1
... ret *= idx
...
>>> f=fac()
>>> next(f)
1
>>> next(f)
2
>>> next(f)
6
>>> next(f)
24
>>> next(f)
120
#!/usr/bin/env python
#
lst=[1,2,3,4]
def func(x):
for i in x:
yield i
res=func(lst)
while True:
print(next(res))
#!/usr/bin/env python
#
def gen(x):
while True:
yield x
x+=1
res=gen(1)
while True:
print(next(res))
yield from lst 等效于 for x in lst; print x
生成器优点
Python使用生气对延迟操作提供了支持,所谓延迟操作,是指在需要的时候才产生结果,而不是立即产生结果,这也是生成器的主要好处;
生成器小结
1、生成器是可迭代对象;
2、实现了延迟计算,省内存;
3、生成器本质和其他的数据类型一样,都是实现了迭代器协议,只不过生成器附加了一个延迟计算省内存的好处;
三元表达式
示例
#!/usr/bin/env python
#
name = 'alex'
print('sb' if name == 'alex' else 'shuaige')
列表解析
# 一般情况下我们需要这样去生成列表
#!/usr/bin/env python
#
lst=[]
for i in range(10):
lst.append('鸡蛋%s'%i)
print(lst)
#三元运算的方式
print(['鸡蛋%s'%i for i in range(10)])
#加入判断语句
print(['鸡蛋%s'%i for i in range(10) if i > 5]) #一元:'鸡蛋%s'%i 二元:for i in range(10) 三元:if i > 5
print(['鸡蛋%s'%i for i in range(10) if i > 5 and i < 8])
#!/usr/bin/env python
#
lst=['鸡蛋%s'%i for i in range(10) if i > 5 and i < 8]
it=lst.__iter__()
print(next(lst.__iter__()))
print(next(lst.__iter__()))
[root@Linux python]# cat day6.py
#!/usr/bin/env python
import os
lst=os.listdir('/var/log')
print([ i for i in lst if str(i).endswith('log')])
[root@Linux python]# python day6.py
['tallylog', 'msg_error.log', 'boot.log', 'cloud-init.log', 'yum.log', 'shadowsocks.log', 'maillog', 'ecs_network_optimization.log', 'ntp.log', 'test2.log', 'test.log', 'lastlog', 'msg_access.log']
#!/usr/bin/env python
#
lst1=[1,2]
lst2=[3,4]
print([(x,y ) for x in lst1 for y in lst2])
列表解析和生成器解析示例
>>> def inc(x):
... print('inc is {0}'.format(x))
... return x + 1
...
>>> inc(1)
inc is 1
2
>>> [ inc(x) for x in range(2) ] #列表解析,直接打印(直接计算)
inc is 0
inc is 1
[1, 2]
>>> ( inc(x) for x in range(2) ) #生成器解析,延迟打印(取值的时候才会计算)
<generator> at 0x7f8f8f729a40>/<generator>
>>> re=( inc(x) for x in range(2) )
>>> next(re)
inc is 0
1
>>>
>>> next(re)
inc is 1
2
示例
def test():
for i in range(4):
yield i
t=test()
for i in t:
print(i)
解析
两者就是一个括号的区别,可以看出,我们的生成器解析,只是在我们从生成器中取值的时候,才会进行计算,而我们的列表解析是直接计算,惰性求值。
next函数用于取出生成器的下一个值
总结
1、把列表解析的[]换成()得到的就是生成器表达式;
2、列表解析与生成器表达式都是一种便利的编程方式,只不过生成器表达式更节省内存;
3、Python不但使用迭代器协议,让for循环变得更加通用,大部分内置函数也是使用迭代器协议访问对象的,例如,sum函数是Python的内置函数,该函数使用迭代器协议访问对象,而生成器实现了迭代器协议,所以,我们可以直接这样亿列本值的和:
print(sum([i for i in range(10)]))
print(sum([i ** 2 for i in range(10)]))
print([ x+y for x,y in zip(lst1,lst2) ])
列表解析([])
是将一个可迭代对象(如列表)转换成另一个列表的工具
生成器表达式(())
不创建列表,只是返回一个生成器。这个生成器在每次计算出一个条目后,才把这个条目产生出来。所以在处理大量数据时更有优势
閱讀更多 動漫資深愛好者和IT 的文章