• 017.Python之生成器、面向过程的编程思想、生成式以及三元表达式


    一、生成器与yield

    (一)什么是生成器

    1.生成器

    生成器就是一种自定义的迭代器,用来返回多次值。

    2.yield与return

    (1)return:

    只能返回一次值,函数就立即结束了。

    (2)yield

    ①可以挂起函数,保存函数的运行状态。

    ②可以用来返回多次值。

    (二)为什么要有生成器

    生成器(自定义迭代器)的优点:节省内存。

    (三)如何得到生成器(自定义的迭代器)

    在函数内一旦存在yield关键字,调用函数并不会执行函数体代码,会得到一个返回值,该返回值就是我们自定义的生成器。

    # 先定义一个函数
    def func():
        print('11111111111')
        print('11111111111')
        yield 1, 2
        print('22221222222')
        yield
        print('33333333333')
        yield 3
        print('44444444444')
        
    g = func()
    print(g)  # <generator object func at 0x0000024C8E355510>
    # 生成器内置有__iter__和__next__方法,所以生成器本身就是一个迭代器
    # g.__iter__()
    # g.__next__()
    
    # 因而我们可以用next(生成器)触发生成器所对应函数的执行,然后遇到yield停下来,将yield后的值当做本次调用的结果返回
    res1 = g.__next__() = next(g)  # 11111111111
    							   # 11111111111
    print(res1)  # (1, 2)
    
    res2 = g.__next__() = next(g)  # 22221222222
    print(res2)  # None
    
    res3 = g.__next__() = next(g)  # 33333333333
    print(res3)  # 3
    
    next(g)  # 44444444444
    		 # StopIteration
    

    my_range小示例

    # # 应用案列
    def my_range(start,stop,step=1):
        while start < stop:
            yield start    #  函数中出现了yield,调用时已不能执行函数体代码,实际上已变成一个生成器generator
            start+=step
    
    g=my_range(1,5) # <generator object my_range at 0x000001891CC0D9E0>
    print(next(g))  # 1  触发函数执行直到遇到yield则停止,将yield后的值返回,并在当前位置挂起函数
    print(next(g))  # 2  再次调用next(g),函数从上次暂停的位置继续执行,直到重新遇到yield...
    print(next(g))  # 3  重复上一步
    print(next(g))  # 4  触发函数执行没有遇到yield则无值返回,即取值完毕抛出异常结束迭代StopIteration	
    
        
    ## 既然生成器对象属于迭代器,那么必然可以使用for循环迭代,如下:
    for n in my_range(1,5):
        print(n) # 1 2 3 4
    

    二、面向过程的编程思想

    (一)什么是编程思想

    编程思想就是编写程序的套路,与具体的技术点无关。

    (二)什么是面向过程

    面向过程核心是过程二字,过程就是解决问题的步骤,即先干啥、再干啥、后干啥,基于面向过程编程就好比在设计一条条的流水线。

    (三)优点与缺点

    1.优点:

    将复杂的问题流程化、进而简单化。

    2.缺点:

    所有环节耦合到一起,环环相扣,如果要修改某个环境,有可能会牵一发而动全身,扩展性差。

    三、三元表达式

    (一)什么是三元表达式

    三元表达式是python为我们提供的一种简化代码的解决方案,语法如下:

    res = 条件成立时返回的值 if 条件 else 条件不成立时返回的值
    

    (二)如何使用

    针对下述场景

    def func(x,y):
        if x > y:
            return x
        else:
            return y
    
    res=func(1,2)
    print(res)  # 2
    

    用三元表达式可以一行解决

    x=1
    y=2
    
    res=x if x > y else y
    print(res)  # 2
    

    四、生成式

    (一)列表生成式

    列表生成式是python为我们提供的一种简化代码的解决方案,用来快速生成列表。

    # 列表生成式:
    l = ['alex_nb', 'lxx_nb', 'wxx_nb', "xxq_nb", 'egon']
    # 取出所有'nb'结尾的组成新的列表
    new_l=[]
    for name in l:
        if name.endswith('nb'):
            new_l.append(name)
    print(new_l)  # ['alex_nb', 'lxx_nb', 'wxx_nb', 'xxq_nb']
    
    new_l=[name for name in l if name.endswith('nb')]  # 快速生成新的列表,['alex_nb', 'lxx_nb', 'wxx_nb', 'xxq_nb']
    
    # 把所有小写字母全变成大写
    new_l=[name.upper() for name in l]
    print(new_l)  # ['ALEX_NB', 'LXX_NB', 'WXX_NB', 'XXQ_NB', 'EGON']
    
    # 把所有的名字去掉后缀_nb
    new_l=[name.replace('_nb','') for name in l]
    print(new_l)  # ['alex', 'lxx', 'wxx', 'xxq', 'egon']
    

    (二)字典生成式

    # 字典生成式
    keys=['name','age','gender']
    dic={key:None for key in keys}
    print(dic)  # {'name': None, 'age': None, 'gender': None}
    
    items=[('name','egon'),('age',18),('gender','male')]
    res={k:v for k,v in items if k != 'gender'}
    print(res)  # {'name': 'egon', 'age': 18}
    

    (三)集合生成式

    # 集合生成式
    keys=['name','age','gender']
    set1={key for key in keys}
    print(set1,type(set1))  # {'gender', 'age', 'name'}  <class 'set'>
    

    (四)生成器表达式

    1.创建一个生成器对象有两种方式

    (1)一种是调用带yield关键字的函数,

    (2)另一种就是生成器表达式,与列表生成式的语法格式相同,只需要将[]换成(),即:

    (expression for item in iterable if condition)
    

    对比列表生成式返回的是一个列表,生成器表达式返回的是一个生成器对象。对比列表生成式,生成器表达式的优点是节省内存(一次只产生一个值在内存中)。

    g=(i for i in range(6) if i > 3)
    # !!!!!!!!!!!强调!!!!!!!!!!!!!!!
    # 此刻g内部一个值也没有
    
    print(g,type(g))  # <generator object <genexpr> at 0x000001F1CE13D9E0> <class 'generator'>
    
    print(next(g))  # 4
    print(next(g))  # 5
    print(next(g))  # StopIteration
    

    如果我们要读取一个大文件的字节数,应该基于生成器表达式的方式完成

    with open('a.txt', mode='rt', encoding='utf-8') as f:
        # 方式一:
        res=0
        for line in f:
            res+=len(line)
        print(res)
    
        # 方式二:
        res=sum([len(line) for line in f])
        print(res)
    
        # 方式三 :效率最高
        res = sum((len(line) for line in f))
        # 上述可以简写为如下形式
        res = sum(len(line) for line in f)
        print(res)
    

    五、内置函数补充

    (一)abs()

    # 取绝对值
    print(abs(-1))  # 1
    print(abs(1))  # 1
    

    (二)all()

    # 2.1、传入的可迭代对象取出的值,全真则真,一假则假
    # 2.2、如果传入的可迭代对象取不出任何值,默认返回True
    
    print(all([1,1,1,True,"abc"]))  # True
    print(all([1,"",1,True,"abc"]))  # False
    print(all([]))  # True
    

    (三)any()

    # 3.1、传入的可迭代对象取出的值,一真则真,全假才假
    # 3.2、如果传入的可迭代对象取不出任何值,默认返回False
    
    print(any([0,None,False,"",1]))  # True
    print(any([]))  # False
    

    (四)callable()

    # 判断一个变量是否可以加括号被调用为函数
    def func():
        pass
    print(callable(func))  # True
    print(callable(len))  # True
    print(callable(10))  # False
    

    (五)进制转换

    # 10进制转换为二  八  十六  进制
    print(bin(11))  # 0b1011
    print(oct(11))  # 0o13
    print(hex(11))  # 0xb
    

    (六)chr()与ord()

    print(ord("a"))  # 97
    print(chr(97))  # a
    

    (七)divmod()

    # 同时取到商与余数
    print(divmod(10,3))  # (3, 1)
    

    (八)enumerate()

    # 得出可迭代对象的序号与值,迭代无序的字典类型也给出序号
    l=[111,222,333]
    for i,item in enumerate(l): #i,item=(0,111)
        print(i,item)
        
    for i,item in enumerate({"k1":111,"k2":222}): #i,item=(0,111)
        print(i,item)
    
  • 相关阅读:
    c#中的Unity容器
    c# Task 篇幅二
    C# Task 篇幅一
    多线程Thread,线程池ThreadPool
    第十二章:二叉查找树(1)
    第十章:基本数据结构(2)
    第十章:基本数据结构(1)
    第十章:基本数据结构(0)
    劝学
    CentOS7安装Docker CE
  • 原文地址:https://www.cnblogs.com/huluhuluwa/p/13185821.html
Copyright © 2020-2023  润新知