• 第四章 函数之装饰器、迭代器、生成器


    4.7 推导式

    1. 列表推导式

      • 基本格式

        v1 = [i for i in 可迭代对象 ]
        v2 = [i for i in 可迭代对象 if 条件 ] # 条件为true才进行append
         1 # 示例一
         2 v1 = [ i for i in 'alex' ]  # ['a','l','e','x']
         3 v2 = [i+100 for i in range(10)] # [100,101,102,...,109]
         4 v3 = [99 if i>5 else 66  for i in range(10)][66,66,66,66,66,66,99,99,99,99]
         5  6 # 示例二
         7 def func():
         8     return 100
         9 v4 = [func for i in range(10)] # [10个func函数]
        10 11 v5 = [lambda : 100 for i in range(10)]
        12 result = v5[9]() # 100
        13 14 # 示例三
        15 def func():
        16     return i
        17 v6 = [func for i in range(10)]
        18 result = v6[5]()    # 9
        19 20 v7 = [lambda :i for i in range(10)]
        21 result = v7[5]()    # 9
        22 23 # 示例四
        24 v8 = [lambda x:x*i for i in range(10)] # 新浪微博面试题
        25 # 1.请问 v8 是什么?# 函数
        26 # 2.请问 v8[0](2) 的结果是什么? # 18
        27 28 # 面试题
        29 def num():
        30     return [lambda x:i*x for i in range(4)]
        31 # num() -> [函数,函数,函数,函数]
        32 print([ m(2) for m in num() ]) # [6,6,6,6]
        33 34 # ##################### 筛选 #########################
        35 v9 = [i for i in range(10) if i > 5]
        View Code
    2. 集合推导式

      v1 = { i for i in 'alex' }
    3. 字典推导式

      v1 = { 'k'+str(i):i for i in range(10) }

       

    4.8 装饰器

    1. 导入

      # 典例一
      v = 1
      v = 2
      print(v)    # 2
      ​
      # 典例二
      def func():
          pass
      v = 10
      v = func
      print(v)    # v 为函数地址
      ​
      # 典例三
      def base():
          print(1)
      def bar():
          print(2)
      bar = base
      bar()   # 1
      # 典例一
      def func():
          def inner():
              pass
          return inner
      v = func()  # inner函数地址
      ​
      # 典例二
      def func(arg):
          def inner():
              print(arg)
          return inner
      v1 = func(1) 
      v1()        # 1
      v2 = func(2)
      v2()        # 2
      ​
      # 典例三
      def func(arg):
          def inner():
              arg()
          return inner
      def f1():
          print(123)
      v1 = func(f1)
      v1()    # 123
      ​
      # 典例四
      def func(arg):
          def inner():
              arg()
          return inner
      ​
      def f1():
          print(123)
          return 666
      ​
      v1 = func(f1)   #inner函数
      result = v1()   #执行f1函数 123
      print(result)   #返回值为None
      ​
      # 典例五
      def func(arg):
          def inner():
              return arg()
          return inner
      ​
      def f1():
          print(123)
          return 666
      ​
      v1 = func(f1)   # inner函数
      result = v1()   # 执行inner函数 123 返回值为f1
      print(result)   #打印f1返回值
      

        

    2. 装饰器基本格式

      def func(age):
      def inner():
      v = arg()
      return v
      return inner
      # 第一步:执行func函数并将下面函数参数传递,相当于:fun(index)
      # 第二步:将func的返回值重新赋值给下面的函数名,index = func(index)
      @func
      def index():
         print(123)
         return 666
      print(index)
    3. 含义

      • 在不改变原函数内部代码的 基础上,在函数执行之前和之后自动执行某个功能

    4. 格式

      • 装饰器编写格式

        def 外层函数(参数)
        def 内层函数(*args,**kwargs)
        return 参数(*args,**kwargs)
        return 内层函数
      • 装饰器应用格式

        @外层函数
        def 参数():
        pass
        index()
      • 问题:为什么要加 *args, **kwargs

        • 可以接收参数函数里面任意值

      • 如果给好几个函数写一个统一的装饰器,怎么办?

        def a1(func):
        def inner(*args,**kwargs)
        return func(*args,**kwargs)
        return inner
           
        @a1
        def f1():
        pass

        @a1
        def f2():
        pass

        @a1
        def f2():
        pass
    5. 关于执行函数的前后

      def a1(func):
         def inner(*args,**kwargs)
        print("调用函数之前")
             data = func(*args,**kwargs)# 执行函数并获取返回值
             print("调用函数之后")
             return data
         return inner

      @a1
      def index():
         print(123)
      index()  
    6. 带参数的装饰器

      # 第一步:执行 ret = xxx(index)
      # 第二步:将返回值赋值给 index = ret
      @xxx
      def index():
         pass

      # 第一步:执行 v1 = uuu(9)
      # 第二步:ret = v1(index)
      # 第三步:index = ret
      @uuu(9)
      def index():
         pass
      # 格式 
      def x(counter):
         def wrapper(fnc):
             def inner(*args,**kwargs)
            data = func(*args,**kwargs)
                 return data
             return inner
         def wrapper
         
      @x(9)
      def index():
         pass
    7. 查看带参数装饰器执行顺序

      def x(counter):
         print('x函数')
         def wrapper(func):
             print('wrapper函数')
             def inner(*args,**kwargs):
                 print('inner函数')
                 if counter:
                     return 123
                 return func(*args,**kwargs)
             return inner
         return wrapper

      @x(True)
      def fun990():
         pass

      @x(False)
      def func10(): # x函数
         pass    # wrapper函数

    4.9 迭代器

    1. 类和对象

    2. 任务展示列表中所有数据

      • while + 索引 + 计数器

      • 迭代器

    3. 迭代器含义

      对某种对象(str/list/tuple/dict/set类创建的对象),可迭代对象中元素逐一获取。

      什么是迭代器:具有' __ next __ ' 的方法且每次调用都能获取可迭代对象中的每个元素(从前到后一一获取)

    4. 迭代器使用

      # 列表转换成迭代器:
      v1 = [1,2,3,4]
      v2 = iter(v1) #v2就是迭代器
      v2 = v1.__iter__()

      # 迭代器想要获取每个值:
      result1 = v2.__next__()
      print(result1)
      result2 = v2.__next__()
      print(result2)
      result3 = v2.__next__()
      print(result3)
      result4 = v2.__next__()
      print(result4)
      result5 = v2.__next__()
      print(result5)
      # 直到报错:StopIteration错误,表示已经迭代完毕。
      # 或者循环获取迭代器中的内容
      while True:
         try:
              val = v2.__next__()
              print(val)
          except Exception as e:
              break
      • 如何判别一个对象是否是迭代器:内部是否有__next__方法

      • for循环实质

        v1 = [11,22,33,44]

        # 1.内部会将v1转换成迭代器
        # 2.内部反复执行 迭代器.__next__()
        # 3.取完不报错
        for item in v1:
           print(item)
    5. 可迭代对象

      • 表象:可以被循环对象就可以称为是可迭代对象:"x" [1,2] {}

        class Foo:
           pass

        obj = Foo()

         

      • 内部具有 __iter__() 方法且返回一个迭代器。

        v1 = [11,22,33,44]
        result = v1.__iter__() #result 就是迭代器
      • 可以被for循环

         

      • 如何让一个对象变成可迭代对象?

        在类中实现__iter__方法且返回一个迭代器(生成器)

        class Foo:
           def __iter__(self):
               return iter([1,2,3,4])
           
        obj = Foo()

        class Foo:
           def __iter__(self):
               yield 1
               yield 2
               yield 3
               
        obj = Foo

        记住:只有能被for循环就是去看内部的iter方法。

    6. 迭代器口诀

      • 取一次就没有了

      • 不取就不执行

    7. 取迭代器的值得方法

      1. list

      2. for循环

      3. next

     

    4.10 生成器

    1. 实质:就是函数的变异

    2. 格式

      # 生成器函数(内部是否包含yield)
      def func():
         print("f1")
         yield 1
         print("f2")
         yield 2
         print("f3")
      # 函数内部不会被执行,返回一个生成对象
      v1 = func()
      # 生成器可以被for循环,一旦开始循环那么函数内部代码就会开始执行
      for item in v1:
         print(item)
      # 无限循环打印1,2,3.....
      def func():
         count = 1
         while True:
             yield count
             count += 1
             
      val = func()

      for item in val:
         print(item)
    3. 总结:函数中如果存在yield,那么该函数就是一个生成器函数,调用生成器函数会返回一个生成器,生成器只有被for循环时,生成器函数内部的代码才会被执行,每次执行都会获取yield返回的值

    4. 练习

      # 读取大文件
      def func():
         """
        分批去读取文件中的内容,将文件的内容返回给调用者。
        :return:
        """
         cursor = 0
         while True:
             f = open('db', 'r', encoding='utf-8')# 通过网络连接上redis
             # 代指   redis[0:10]
             f.seek(cursor)
             data_list =[]
             for i in range(10):
                 line = f.readline()
                 if not line:
                     return
                 data_list.append(line)
             cursor = f.tell()
             f.close()  # 关闭与redis的连接


             for row in data_list:
                 yield row


      for item in func():
         print(item)

      redis 源码示例

    个人站点 www.danpinsuiyue.com ,欢迎给各位大神莅临本博客空间。
  • 相关阅读:
    How to run Java main class and pass application arguments in Maven?
    【转】三年后再反思我的" Java Web项目管理得失谈"
    Object.keys()
    angular $resource 的 get请求 和 post请求
    vue 自定义 移动端筛选条件
    获取当前时间 YYYY-MM-DD
    vue-router 二级路由
    blob 对象 实现分片上传 及 显示进度条
    js性能优化之函数节流(分流函数)
    vue + vue-lazyload 实现图片懒加载
  • 原文地址:https://www.cnblogs.com/dpsy921/p/11324111.html
Copyright © 2020-2023  润新知