• Python20-Day04


    ##########迭代器、生成器和面向过程编程##########

    一、迭代器

      迭代器是一个重复的过程,每次重复即一次迭代,并且每次迭代的结果都是下一次迭代的初始值;

    l = [1,2,3]
    count = 0
    while count < len(l):
        print(l[count])
        count+=1

      为何要有迭代器?

        对于序列类型:字符串,列表,元组,可以通过使用索引的方式迭代取出其包含的元素,但是对于字典,集合文件等类型是没有索引的,若还想取出其内部包含的元素,

        就必须使用不依赖于索引的迭代方式---迭代器。

      什么是可迭代对象?

        可迭代的对象指的是内置有__iter__方法的对象,即obj.__iter__,如下:

    'hello'.__iter__
    (1,2,3).__iter__
    [1,2,3].__iter__
    {'a':1}.__iter__
    {'a','b'}.__iter__
    open('a.txt').__iter__

      什么是迭代器对象?

        可迭代对象执行obj.__iter__()得到的结果就是迭代器对象

        而迭代器器对象指的是内置有__iter__又内置有__next__方法的对象

        文件类型是迭代器对象:

    open('a.txt').__iter__()
    open('b.txt').__next__()

      注意:

        迭代器对象一定是可迭代对象,而可迭代对象不一定是迭代器对象。

      迭代器对象的使用

    dic={'a':1,'b':2,'c':3}
    # iter_dic = dic.__iter__()  #得到迭代器对象,迭代器对象既有__iter__又有__next__。
    # print(iter_dic.__iter__() is iter_dic)   #True 迭代器.__iter__()得到的仍然是迭代器本身
    # print(iter_dic.__next__())  #等同于next(iter_dic)
    # print(iter_dic.__next__())
    # print(iter_dic.__next__())
    # print(iter_dic.__next__())  #元素迭代完成,会抛出异常StopIteration
    
    #有了迭代器,就可以不依赖索引迭代取值了   需要自己捕捉异常,控制next。
    iter_dic = dic.__iter__()
    print(iter_dic)
    while 1:
        try:
            k = next(iter_dic)
            print(dic[k])
        except StopIteration:
            break

      for循环

    dic={'a':1,'b':2,'c':3}
    for key in dic:
        print(key,dic[key])
    #基于for循环,可以不再依赖索引取值
    #for循环的工作原理:
      1. 执行in后对象的dic.__iter__(),得到一个迭代器对象iter_dic
      2. 执行next(iter_dic),将得到的值赋值给k,然后执行循环体代码
      3. 重复过程2,直到捕捉到异常StopIteration

       迭代器的优缺点:

        优点:

          - 提供一种统一的不依赖于索引的迭代方式

          - 惰性计算,节省内存

        缺点:

          - 无法获取长度(只有在next完毕才知道到底有几个值)

          - 一次性的,只能往后走,不能往前退

    二、生成器

      什么是生成器?

        只要函数内部包含有yield关键字,那么函数名()得到的结果就是生成器,并且不会执行函数内部代码。

    def func():
        print('====>first')
        yield 1
        print('====>second')
        yield 2
        print('====>third')
        yield 3
        print('====>end')
    
    print(func())
    # g=func()
    # print(g)
    # print(next(g))
    # print(next(g))
    # print(next(g))
    # print(next(g))

      生成器就是迭代器

        g.__iter__

        g.__next__

        res = next(g)

        print(res)

      练习题:1、自定义函数模拟range(1,7,2)

    #1、自定义函数模拟range(1,7,2)
    def my_range(start,stop,step=1):
        while True:
            if start < stop:
                yield start
            start+=step
    g = my_range(1,7,2)    #g为生成器  生成器就是迭代器,可以通过迭代器迭代取值
    print(next(g))
    print(next(g))
    print(next(g))
    # for i in my_range(1,7,2):  #也可以通过for循环取值
    #     print(i)

          2、模拟管道,实现功能:tail -f access.log | grep '404'

    import time
    def tail(filepath):
        with open(filepath,'rb') as f:
            f.seek(0,2)
            while True:
                line = f.readline()
                if line:
                    yield line
                else:
                    time.sleep(0.2)
    def grep(parttern,lines):
        for line in lines:
            line = line.decode('utf-8')
            if parttern in line:
                yield line
    
    
    for line in grep('404',tail('access.log')):
        print(line,end='')

    三、yield总结

      #1、把函数做成迭代器

      #2、对比return,可以返回多次值,可以挂起/保存函数的运行状态

    四、面向过程编程

      #1、强调:面向过程编程绝对不是用函数编程,面向过程是一种编程思想、思路,而编程思路是不依赖于具体的语言或者语法的。也可以说即使我们不依赖于函数,也可以基于面向过程的思想编写程序

      #2、定义

        面向过程的核心是过程,过程指的是解决问题的步骤,即先干什么后干什么。

        基于面向过程设计程序就好比是设计一条流水线,是一种机械式的思维方式

      #3、优点

        复杂的问题流程化,进而简单化

      #4、缺点

        可扩展性差,修改流水线的任意一个阶段,都会牵一发而动全身

      #5、应用

        扩展性要求不高的场景,典型案例Linux内核

    ##########三元表达式、列表推导式、生成器表达式、递归、匿名函数、内置函数##########

    一、三元表达式、列表推导式、生成器表达式

      1、三元表达式 

    name = input('姓名:> ').strip()
    res = 'NB' if name == 'alex' else 'TNB'
    print(res)

      2、列表推导式

    # egg_list = []
    # for i in range(1,10):
    #     egg_list.append('鸡蛋%s' %i)
    # print(egg_list)
    
    egg_list = ['鸡蛋%s' %i for i in range(1,10)]
    print(egg_list)

      3、生成器表达式

      #1、把列表推导式的[]换成()就是生成器表达式

    chicken = ('鸡蛋%s' %i for i in range(1,5))
    print(chicken) #chicken = <generator object <genexpr> at 0x00000000021768E0>
    
    # print(next(chicken))  #鸡蛋1
    # print(next(chicken))  #鸡蛋2
    # print(next(chicken))  #鸡蛋3
    
    print(list(chicken)) #['鸡蛋1', '鸡蛋2', '鸡蛋3', '鸡蛋4', ]   因为chicken可迭代,因而可以转换成列表

      #2、优点:省内存,一次只产生一个值在内存中

     二、声明式编程练习题

    #1、将names=['egon','alex_sb','wupeiqi','yuanhao']中的名字全部变大写
    names=['egon','alex_sb','wupeiqi','yuanhao']
    
    res = [name.upper() for name in names]
    print(res)   #['EGON', 'ALEX_SB', 'WUPEIQI', 'YUANHAO']
    #2、将names=['egon','alex_sb','wupeiqi','yuanhao']中以sb结尾的名字过滤掉,然后保存剩下的名字长度
    names=['egon','alex_sb','wupeiqi','yuanhao']
    # res = [name for name in names if 'sb' not in  name]   #以sb结尾的名字过滤掉    res = ['egon', 'wupeiqi', 'yuanhao']
    res = [len(name) for name in names if 'sb' not in name]  #[4, 7, 7]
    print(res)
    #3、求文件a.txt中最长的行的长度(长度按字符个数算,需要使用max函数)
    #笨方法
    # num_list=[]
    # with open('a.txt','r',encoding='utf-8') as f:
    #     lines = f.readlines()
    #     for line in lines:
    #         num_list.append(len(line))
    # print(max(num_list))
    #声明式方法
    with open('a.txt',encoding='utf-8') as f:
        print(max(len(line)for line in f))

    三、内置函数

      现阶段需要掌握的:

      divmod

        python divmod()函数把除数和余数运算结果结合起来,返回一个包含商和余数的元组(a // b,a % b)

    >>> divmod(7,2)
    (3, 1)
    >>> divmod(8,2)
    (4, 0)

      enumerate

        enumerate是用来遍历可迭代容器中的元素,同时通过一个计数器变量记录当前元素所对应的索引值。

    #示例:
    names = ['Bob', 'Alice', 'Guido']
    for index, value in enumerate(names):
        print(f'{index}: {value}')
    #输入如下内容:
    0: Bob
    1: Alice
    2: Guido

        这个循环遍历了name列表的所有元素,并通过增加从零开始的计数器变量为每个元素生成索引。

        enumerate()函数允许为循环自定义起始索引值。enumerate()函数中接收一个可选参数,该参数允许为本次循环中的计数器变量设置初始值。

    names = ['Bob', 'Alice', 'Guido']
    for index, value in enumerate(names, 1):
        print(f'{index}: {value}')
    1: Bob
    2: Alice
    3: Guido

       

    enumerate是Python的一个内置函数。你应该充分利用它通过循环迭代自动生成的索引变量。
    索引值默认从0开始,但也可以将其设置为任何整数。
    enumerate函数是从2.3版本开始被添加到Python中的,详情见PEP279。
    Python的enumerate函数可以帮助你编写出更加Pythonic和地道的循环结构,避免使用笨重且容易出错的手动生成索引。
    为了充分利用enumerate的特性,一定要研究Python的迭代器和数据结构解包功能。
    
    作者:vimiix
    链接:https://juejin.im/post/5a31146251882503eb4b4755
    来源:掘金
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

      eval

        功能:将字符串str当成有效的表达式来求值并返回结果。

        参数:

          source : 一个python表达式或者函数compile()返回的代码对象

          globals : 可选,必须是dictionary

          locals : 可选,任意map对象

    可以把list,tuple,dict和string相互转化。
    #################################################
    字符串转换成列表
    >>>a = "[[1,2], [3,4], [5,6], [7,8], [9,0]]"
    >>>type(a)
    <type 'str'>
    >>> b = eval(a)
    >>> print b
    [[1, 2], [3, 4], [5, 6], [7, 8], [9, 0]]
    >>> type(b)
    <type 'list'>
    #################################################
    字符串转换成字典
    >>> a = "{1: 'a', 2: 'b'}"
    >>> type(a)
    <type 'str'>
    >>> b = eval(a)
    >>> print b
    {1: 'a', 2: 'b'}
    >>> type(b)
    <type 'dict'>
    #################################################
    字符串转换成元组
    >>> a = "([1,2], [3,4], [5,6], [7,8], (9,0))"
    >>> type(a)
    <type 'str'>
    >>> b = eval(a)
    >>> print b
    ([1, 2], [3, 4], [5, 6], [7, 8], (9, 0))
    >>> type(b)
    <type 'tuple'>
  • 相关阅读:
    动态规划-矩阵链乘法
    钢条切割问题
    代码着色
    Sublime配置C和C++编译运行环境
    Guava中集合类的简单实用
    Junit单元测试入门
    Sublime Text 快捷键
    Editplus 的配色方案
    利用Wireshark任意获取QQ好友IP实施精准定位
    linux下实现定时执行php脚本
  • 原文地址:https://www.cnblogs.com/mrwang1101/p/8109339.html
Copyright © 2020-2023  润新知