Python基础----生成器、三元表达式、列表生成式、生成器表达式

生成器

生成器函数:函数体内包含有yield关键字,该函数执行的结果是生成器,生成器在本质上就是迭代器。

复制代码
def foo():
    print('first------>')
    yield 1
    print('second----->')
    yield 2
    print('third----->')
    yield 3
    print('fouth----->')
g=foo()
from collections import Iterator
print(isinstance(g,Iterator))
print(g)
复制代码

yield的功能:

  1.与return类似,都可以返回值,但不一样的地方在于可以有多个yield,每个yield能够返回一次值,而return只能返回一次值就结束了

  2.为函数封装好了__iter__和__next__方法,把函数的执行结果做成了迭代器

  3.遵循迭代器的取值方式obj.__next__(),触发的函数的执行,函数暂停与再继续的状态都是由yield保存的

生成器的使用

复制代码
def foo():
    print('first------>')
    yield 1
    print('second----->')
    yield 2
    print('third----->')
    yield 3
    print('fouth----->')
g=foo()
print(g.__next__())
print(g.__next__())
print(g.__next__())
# print(g.__next__())

输出结果
first------>
1
second----->
2
third----->
3
复制代码

第一次g.__next__()在函数体的第一个yield结束后暂停,并执行前面的指令

第二次g.__next__()在函数体的第二个yield结束后暂停,并执行前面的指令

第三次g.__next__()在函数体的第三个yield结束后暂停,并执行前面的指令

如果来第四次g.__next__()方法,将抛出StopIteration提示错误

for循环调用:for会自动处理StopIteration,当遇到StopIteration自动停止

for i in g: #obj=g.__iter__()   #obj.__next__()
    print(i)

输出结果

复制代码
first------>
1
second----->
2
third----->
3
fouth----->
复制代码

如果生成器函数不赋值变量,那么每次执行都是全新的生成器函数,并没有迭代的效果,如下:

复制代码
def foo():
    print('first------>')
    yield 1
    print('second----->')
    yield 2
    print('third----->')
    yield 3
    print('fouth----->')
print(foo().__next__())
print(foo().__next__())
print(foo().__next__())

输出结果
first------>
1
first------>
1
first------>
1
复制代码

使用print测试foo函数,会发现,同一时间输出的foo函数,内存地址并不同

print(foo(),foo(),foo())

输出结果:
<generator object foo at 0x00000251392F1E60> <generator object foo at 0x00000251392F1DB0> <generator object foo at 0x00000251392F1EB8>

生成器示例:一个yield返回多个值

复制代码
def countdown(n):
    print('starting countdown')

    while n > 0:
        yield n
        n-=1
    print('stop countdown')
g=countdown(5)
for i in g:
    print(i)

输出结果
starting countdown
5
4
3
2
1
stop countdown
复制代码

生成器模拟linux命令:tail -f a.txt |grep 'error' |grep '404'

当在a.txt文件中输入字符串,如果包含error并且包含404,那么将打印出该行,其他不打印

复制代码
import time
def tail(filepath,encoding='utf-8'):
    with open(filepath,encoding=encoding) as f:
        f.seek(0,2)
        while True:
            # f.seek(0, 2) #不行
            line=f.readline()
            if line:
                # print(line,end='')
                yield line
            else:
                time.sleep(0.5)

def grep(lines,pattern):
    for line in lines:
        if pattern in line:
            # print(line)
            yield line

g1=tail('a.txt')
g2=grep(g1,'error')
g3=grep(g2,'404')
for i in g3:
    print(i)
复制代码

三元表达式

简化代码量:比较两个数的大小,可以用以下if语句完成

 

x=2
y=3
if x > y:
    print(x)
else:
    print(y)

 

使用三元表达式:可以简化成一行解决

res='x' if x > y else 'y'
print(res)

三元表达式即 'x' if x > y else 'y'

当条件为真,那么输出条件左边的值,当条件为假则输出右边的值

示例:

复制代码
def max2(x,y):
    # if x > y:
    #     return x
    # else:
    #     return y
    return x if x > y else y
print(max2(1,2))
复制代码

列表生成式

简化生成列表的代码量

如:将s='hello'的字符串转化成大写,并将每一个字符转化成列表元素,即['H','E','L','L','O']

普通循环代码:

s='hello'
l=[]
for i in s:
    res=i.upper()
    l.append(res)
print(l)

列表解析代码:

s='hello'
res=[i.upper() for i in s]
print(res)

使用列表解析能够简化简单的代码生成

列表生成式说明:

示例:

l=[1,31,73,84,57,22]
print([i for i in l if i > 50])    #l列表中大于50的元素生成一个新列表
print([i for i in l if i < 50])    #l列表中小于50的元素生成一个新列表
print([i for i in l if i > 20 and i < 50]) #l列表中大于20小于50的元素生成一个新列表

生成器表达式

类似于列表生成式,只不过将中括号换成小括号,每次执行next将输出一个元素,占用内存小,每次只占用一个元素的内存空间

复制代码
g=(i for i in range(1000))
print(g)    #生成器
print(next(g))    #每次执行next(g)即可输出一个元素
print(next(g)) 
print(next(g)) 
print(next(g)) 

输出结果
<generator object <genexpr> at 0x00000205FFE91E60>
0
1
2
3
复制代码
posted @ 2017-07-04 16:57  云养猫  阅读(249)  评论(0编辑  收藏  举报