python迭代器(函数名的应用,新版格

发布时间:2019-06-05 21:16:07编辑:auto阅读(1694)

    1. 内容大纲

      1. 函数名的运用
      2. 新特性:格式化输出
      3. 迭代器:
        • 可迭代对象
        • 获取对象的方法 dir()
        • 判断一个对象是否是可迭代对象
        • 小结
        • 迭代器
        • 迭代器的定义
        • 判断一个对象是否是迭代器
        • 迭代器的取值
        • 可迭代对象如何转化成迭代器
        • while循环模拟for循环机制
        • 小结
        • 可迭代对象与迭代器的对比
    2. 详细内容:

      1. 函数名的运用:

        函数名的定义和变量的定义几乎一致,在变量的角度,函数名其实就是一个变量,具有变量的功能:可以赋值;但是作为函数名他也有特殊的功能就是加上()就会执行对应的函数,所以我们可以把函数名当做一个特殊的变量。

        1:函数名指向的是函数的内存地址,函数名 + () 就可以执行此函数
         a =1
         a()#TypeError: 'int' object is not callable  不可调用
        
         a = 1
         b = 2
         print(a + b)#3  a与b可以相加,与a,b这两个变量本身无关,与变量指向的对象有关。
        
         def func():
             print(666)
         func()#666  之所以func + () 可以执行,与func (函数名) 指向的内存地址有关。函数的内存地址()才是执行这个函数的关键
         print(func,type(func))#<function func at 0x000001CB29A71E18> <class 'function'>
        
        2:函数名就是变量(函数名可以赋值给其他变量)
         def func():
             print(666)
         f = func   #变量的赋值
         f1 = f
         f2 = f1
         f()#666
         func()#666
         f1()#666
         f2()#666
        
        
         def func():
             print('in func')
         def func1():
             print('in func1')
         func1 = func
         func1()#in func
        
        
        3:函数名可以作为容器类数据类型的元素
         def func1():
             print('in func1')
         def func2():
             print('in func2')
         def func3():
             print('in fnc3')
         l1 = [func1,func2,func3]
         for i in l1:
             i()
        # # in func1
        # # in func2
        # # in fnc3
        
        # #类比:
         a = 1
         b = 2
         c = 3
         l1 = [a,b,c]
         print(l1)#[1, 2, 3]
        
        4;函数名可以作为函数的参数
         def func(a):
             print(a)
             print('in func')
         b = 3
         func(b)
        # # 3
        # # in func
        
        
         def func():
             print('in func')
         def func1(x):
             x()
             print('in func1')
         func1(func)
        # # in func
        # # in func1
        
        5:函数名可以作为函数的返回值
         def func():
             print('in func')
         def func1(x):       # 传参相当于x = func
             print('in func1')
             return x
         ret = func1(func)
         ret()  #相当于func()     # ret, x, func都是指向的func这个函数的内存地址
        # # in func1
        # # in func
        
      2. 新特性:格式化输出

        [1]格式花输出 %s format
        
         name = '太白'
         age = 18
         msg ='我叫%s,今年%s' %(name,age)
         msg1 = '我叫{},今年{}'.format(name,age)
         print(msg)#我叫太白,今年18
         print(msg1)#我叫太白,今年18
        
        
        [2]python3.6之后的新特性:格式化输出 F 或 f :
        
         name = '太白'
         age = 18
         msg = f'我叫{name},今年{age}'
         print(msg)#我叫太白,今年18
        
        (1)可以加任意表达式:
        
         dic = {'name':'alex','age':18}
         msg = f"我叫{dic['name']},今年{dic['age']}"
         print(msg)#我叫alex,今年18
        
         count = 7
         print(f'最终结果是:{count**2}')#最终结果是:49
         name = 'barry'
         msg = f'我的名字是{name.upper()}'
         print(msg)#我的名字是BARRY
        
         l1 = ['太白金星', 18]
         msg = f'姓名:{l1[0]},年龄:{l1[1]}.'
         print(msg)  # 姓名:太白金星,年龄:18.
        
        (2)结合函数写:可以用函数完成相应的功能,然后将返回值返回到字符串相应的位置
         def _sum(a,b):
             return a + b
         msg = f'最终的结果是:{_sum(10,20)}'
         print(msg)#最终的结果是:30
        
        (3)多行f:
          name = 'barry'
          age = 18
          ajd = 'handsome'
          speaker = f'Hi {name}.'\
                    f'You are {age} years old.'\
                    f'You are a {ajd} guy!'
          print(speaker)
        
        (4)其它:
        print(f"{{73}}")  # {73}
        print(f"{{{73}}}")  # {73}
        print(f"{{{{73}}}}")  # {{73}}
        
        注意: ! , : { } ;这些标点不能出现在{} 这里面。
        print(f'{;12}')  # 报错
        # 所以使用lambda 表达式会出现一些问题。
        # 解决方式:可将lambda嵌套在圆括号里面解决此问题。
         x = 5
         y = 4
        print(f'{(lambda x:x*2) }')#<function <lambda> at 0x000001C5278F1E18>   (lambda x:x*2)相当于函数的内存地址
        print(f'{(lambda x:x*2) (x)}')#10     函数内存地址+()  函数执行
        print(f'{(lambda x,y:x + y) (5,4)}')#9

        优点:

        1. 结构更加简化。

        2. 可以结合表达式,函数进行使用。

        3. 效率提升很多。

      3. 迭代器:

        • 可迭代对象:

          字面意思:对象?:python中一切皆对象。一个实实在在存在的值,对象。

          ​ 可迭代?:更新迭代。重复的,循环的一个过程,更新迭代每次都有新的内容,

          ​ 可迭代对象-->可以进行循环更新的一个实实在在值。

          专业角度:可迭代对象--> 内部含有'__iter__'方法的对象,可迭代对象。

          目前学过的可迭代对象:str bytes list tuple dict set range

        • 获取对象的所有方法并且以字符串的形式表现:dir() 会返回一个列表,这个列表中含有该对象的以字符串的形式所有方法名

        • 判断一个对象是否是可迭代对象:

          '__iter__'`  in dir(对象)
          
           s1 = 'asdfghj'
           print(dir(s1))
           print('__iter__' in dir(s1))#True
          
           l1 = [1,2,3]
           print(dir(l1))
           print('__iter__' in dir(l1))#True
          
           b1 = b'wert'
           print(dir(b1))
           print('__iter__' in dir(b1))#True
          
           print('__iter__' in dir(range(10)))#True
          
        • 优缺点:

          • 优点:

            1. 存储的数据直接能打印显示,比较直观。
            2. 拥有的方法比较多,操作方便。
          • 缺点:

            1. 占用内存。

            2. 不能直接通过for循环进行取值,不能直接取值(索引,key除外)。

              • 可迭代对象不能迭代取值(除去索引,key以外)
              • for内部先将可迭代对象转化为迭代器,然后用next对迭代器取值。
        • 迭代器

        • 迭代器的定义

          • 字面意思:更新迭代,器:工具:可更新迭代的工具。
          • 专业角度:内部含有'__iter__'方法并且含有'__next__'方法的对象就是迭代器。
          • 迭代器是这样的对象:实现了无参数的__next__方法,返回序列中的下一个元素,如果没有元素了,那么抛出StopIteration异常.python中的迭代器还实现了__iter__方法,因此迭代器也可以迭代。 出自《流畅的python》
          • 可以判断是否是迭代器:'__iter__' and '__next__' 在不在dir(对象)
        • 判断一个对象是否是迭代器:

          with open('文件1',encoding='utf-8',mode='w') as f1:
              print(('__iter__' in dir(f1)) and ('__next__' in dir(f1)))
          
          目前学过的迭代器:文件句柄
          
           s = 'asdff'
           print('__next__' in dir(s))# False
        • 转化,取值 :

          • 1.可迭代对象转化为迭代器:对可迭代对象操作,形成一个迭代器。str还是str,list还是list

          • 2.对迭代器取值:一个next() 取一个值,少一个next()可以,多一个就会报错.

            • 可迭代对象是不可以一直迭代取值的(除去用索引,切片以及Key),但是转化成迭代器就可以了,迭代器是利用__next__()进行取值

            • 迭代器利用next取值:一个next取对应的一个值,如果迭代器里面的值取完了,还要next,那么就报StopIteration的错误。
          s1 = 'asdf'
          obj = iter(s1)  #转化为迭代器
          print(obj)#<str_iterator object at 0x000002216DB77828>
          print(next(obj))#a
          print(next(obj))#s
          print(next(obj))#d
          print(next(obj))#f
          
          s1 = 'asdf'
          obj = s1.__iter__()   #转化为迭代器
          print(obj)#<str_iterator object at 0x000001FE307877F0>
          print(obj.__next__())#a
          print(obj.__next__())#s
          print(obj.__next__())#d
          print(obj.__next__())#f
          
          
          l1 = [11,22,33,44,55,66]
          obj = l1.__iter__()
          print(obj)
          print(obj.__next__())  #对迭代器取值
          print(obj.__next__())
          print(obj.__next__())
          print(obj.__next__())
          print(obj.__next__())
          print(obj.__next__())
          
          l1 = [11,22,33,44,55,66]
          obj = iter(l1)
          print(obj)
          print(next(obj))  #对迭代器取
          print(next(obj))
          print(next(obj))
          print(next(obj))
          print(next(obj))
          print(next(obj))
          
          
          #
           l1 = [11,22,33,44,55,66,77,88,99,1010,1111,1212]
           count = 0
           for i in l1:
               if count == 4:
                   break
               else:
                   print(i)
               count += 1
          # # 11
          # # 22
          # # 33
          # # 44
          
           count = 0
           for i in l1:
               if count == 6:
                   break
               else:
                   print(i)
               count += 1
          # # 11
          # # 22
          # # 33
          # # 44
          # # 55
          # # 66
          
          
          
          #迭代器永远会记住取值的位置
           l1 = [11,22,33,44,55,66,77,88,99,1010,1111,1212]
           obj = iter(l1)
           for i in range(4):
               print(next(obj))
          # # 11
          # # 22
          # # 33
          # # 44
          
           for i in range(6):
               print(next(obj))
          # # 55
          # # 66
          # # 77
          # # 88
          # # 99
          # # 1010
          
          
           l1 = [11,22,33,44,55,66,77,88,99,1010,1111,1212]
           for i in l1:
               print(i)
          
          
        • while循环模拟for循环机制【面试经常考】

          将可迭代对象转换成迭代器,然后利用next进行取值,最后利用异常处理处理StopIteration抛出的异常
          l1 = [11,22,33,44,55,66,77,88,99,1111,1133,15652]
          # 将可迭代对象转化成迭代器。
          obj = iter(l1)
          while 1:
              try:
                  print(next(obj))
              except StopIteration:
                  break
        • 小结:

          • 字面意思:更新迭代,器:工具:可更新迭代的工具。
          • 专业角度:内部含有'__iter__'方法并且含有'__next__'方法的对象就是迭代器。
          • 优点:
            1. 节省内存。
            2. 惰性机制, next一次,取一个值,绝不过多取值。
          • 缺点:
            • 速度慢。
            • 不走回头路。 取值时不走回头路,只能一直向下取值
        • 可迭代对象与迭代器的对比:

          • 可迭代对象:可迭代对象是一个操作方法比较多,比较直观,存储数据相对少(几百万个对象,8G内存是可以承受的)的一个数据集。
          • 应用:当你侧重于对于数据可以灵活处理,并且内存空间足够,将数据集设置为可迭代对象是明确的选择。
          • 迭代器:迭代器是非常节省内存,可以记录取值位置,可以直接通过循环+next方法取值,但是不直观,操作方法比较单一的数据集。
          • 应用:当你的数据量过大,大到足以撑爆你的内存或者你以节省内存为首选因素时,将数据集设置为迭代器是一个不错的选择。
    3. 总结

      1. 格式化输出 ***
      2. 函数名的应用。***
      3. 对比:迭代器是什么? 迭代器的优缺点。可迭代对象转化成迭代器。next取值. ***

关键字