zoukankan      html  css  js  c++  java
  • 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
    复制代码
  • 相关阅读:
    c:forTokens标签循环输出
    jsp转long类型为date,并且格式化
    spring中@Param和mybatis中@Param使用区别(暂时还没接触)
    734. Sentence Similarity 有字典数组的相似句子
    246. Strobogrammatic Number 上下对称的数字
    720. Longest Word in Dictionary 能连续拼接出来的最长单词
    599. Minimum Index Sum of Two Lists两个餐厅列表的索引和最小
    594. Longest Harmonious Subsequence强制差距为1的最长连续
    645. Set Mismatch挑出不匹配的元素和应该真正存在的元素
    409. Longest Palindrome 最长对称串
  • 原文地址:https://www.cnblogs.com/chenqizhou/p/7117439.html
Copyright © 2011-2022 走看看