• python — 装饰器、迭代器


    1 装饰器

    1.1目的、应用场景:

    • 目的:

      在不改变原函数内部代码的基础上,在函数执行前后自定义功能。

    • 应用场景:

      想要为函数扩展功能时,可以选择用装饰器。

    1.2 编写装饰器和应用

      1. 基本装饰器

        # 装饰器的编写格式     (双层嵌套函数)
        def 外层函数(参数):
        	def 内层函数(*arg,**kwarg)
        		return 参数(*arg,**kwarg)
        	return 内层函数
        
        #装饰器的应用格式
        @外层函数
        def 要装饰的函数()
        	pass
        
        # 执行函数,自动触发装饰器了
        要装饰的函数()
        

        练习题

        def func(arg):
            def inner():
                print('before')
                v = arg()
                print('after')
                return v 
            return inner 
        
        def index():
            print('123')
            return '666'
        
        
        # 示例一
        v1 = index() # 执行index函数,打印123并返回666赋值给v1.
        
        # 示例二
        v2 = func(index) # v2是inner函数,arg=index函数
        index = 666 
        v3 = v2()
        
        # 示例三
        v4 = func(index)
        index = v4  # index ==> inner 
        index()
        
        # 示例四
        index = func(index)
        index()
        
        def func(arg):
            def inner():
                v = arg()
           return v 
            return inner 
        
        # 第一步:执行func函数并将下面的函数参数传递,相当于:func(index)
        # 第二步:将func的返回值重新赋值给下面的函数名。 index = func(index)
        @func 
        def index():
            print(123)
            return 666
        
        print(index)
        
        # 计算函数执行时间
        
        def wrapper(func):
        

      def inner():
      start_time = time.time()
      v = func()
      end_time = time.time()
      print(end_time-start_time)
      return v
      return inner

      @wrapper
      def func1():
      time.sleep(2)
      print(123)
      @wrapper
      def func2():
      time.sleep(1)
      print(123)

      def func3():
      time.sleep(1.5)
      print(123)

      func1()

      
      注:问题:为什么要加*arg、**kwarg
      
      理解:
      
      
    • 变量赋值

           def func():
          print(1)
               
      v1 = func
           func = 666
           ```
         
         - 看看到底return的是什么?
         
         - 自己有找自己的,自己没有到上一级作用域去找 
         
      

    背会:

         @xx  # index = xx(index)
    def index():
             pass
    index()
         ```
      
    - 2. 关于参数
    
         ```python
         def x(func):
             def inner(a1):
                 return func(a1)
             return inner 
         
         @x
         def index(a1):
         	pass
         ```
    
         ```python
         def x(func):
             def inner(a1,a2):
                 return func(a1,a2)
             return inner 
         
         @x
         def index(a1,a2):
         	pass
         
         # index = inner
         index(1,2)
         
         # ################################### 参数统一的目的是为了给原来的index函数传参
         def x(func):
             def inner(a1,a2):
                 return func()
             return inner 
         
         @x
         def index():
         	pass
         # func = 原来的index函数u
         # index = inner
         index(1,2)
         ```
    
         如果给好几个函数写一个统一的装饰器,怎么办?
    
         ```python
         def x1(func):
             def inner(*args,**kwargs):
                 return func(*args,**kwargs)
             return inner 
         
         @x1
         def f1():
             pass
         
         @x1
         def f2(a1):
             pass
         @x1
         def f3(a1,a2):
             pass 
         ```
    
         装饰器建议写法:
    
         ```python
         def x1(func):
             def inner(*args,**kwargs):
                 data = func(*args,**kwargs)
                 return data
             return inner 
         ```
    
    - 3. 带参数的装饰器
    
         ```python
         # 第一步:执行 v1 = uuu(9)
         # 第二步:ret = v1(index)
         # 第三步:index = ret 
         @uuu(9)
         def index():
             pass
         ```
    
         ```python
         # ################## 普通装饰器 #####################
         def wrapper(func):
             def inner(*args,**kwargs):
                 print('调用原函数之前')
                 data = func(*args,**kwargs) # 执行原函数并获取返回值
                 print('调用员函数之后')
                 return data
             return inner 
         
         @wrapper
         def index():
             pass
         
         # ################## 带参数装饰器 #####################
         def x(counter):
             def wrapper(func):
                 def inner(*args,**kwargs):
                     data = func(*args,**kwargs) # 执行原函数并获取返回值
                     return data
                 return inner 
         	return wrapper 
         
         @x(9)
         def index():
             pass
         ```
    
         练习题
    
         ```python
         # 写一个带参数的装饰器,实现:参数是多少,被装饰的函数就要执行多少次,把每次结果添加到列表中,最终返回列表。
         def xxx(counter):![](https://img2018.cnblogs.com/blog/1646753/201907/1646753-20190719213053775-1588807446.png)
    
    
             print('x函数')
             def wrapper(func):
                 print('wrapper函数')
                 def inner(*args,**kwargs):
                     v = []
                     for i in range(counter):
                         data = func(*args,**kwargs) # 执行原函数并获取返回值
                         v.append(data)
                     return v
                 return inner
             return wrapper
         
         @xxx(5)
         def index():
             return 8
         
         v = index()
         print(v)
         
         # 写一个带参数的装饰器,实现:参数是多少,被装饰的函数就要执行多少次,并返回最后一次执行的结果
         def xxx(counter):
             print('x函数')
             def wrapper(func):
                 print('wrapper函数')
                 def inner(*args,**kwargs):
                     for i in range(counter):
                         data = func(*args,**kwargs) # 执行原函数并获取返回值
                     return data
                 return inner
             return wrapper
         
         @xxx(5)
         def index():
             return 8
         
         v = index()
         print(v)
         # 写一个带参数的装饰器,实现:参数是多少,被装饰的函数就要执行多少次,并返回执行结果中最大的值。
         def xxx(counter):
             print('x函数')
             def wrapper(func):
                 print('wrapper函数')
                 def inner(*args,**kwargs):
                     value = 0
                     for i in range(counter):
                         data = func(*args,**kwargs) # 执行原函数并获取返回值
                         if data > value:
                             value = data 
                     return value
                 return inner
             return wrapper
         
         @xxx(5)
         def index():
             return 8
         
         v = index()
         print(v)
         ```
    
         ```
         def x(counter):
             print('x函数')
             def wrapper(func):
                 print('wrapper函数')
                 def inner(*args,**kwargs):
                     if counter:
                         return 123
                     return func(*args,**kwargs)
                 return inner
             return wrapper
         
         @x(True)
         def fun990():
             pass
         
         @x(False)
         def func10():
             pass
         ```
    
    
    ### 2 迭代器
    
    自己不会写迭代器,只需要会用。
    
    任务:请展示列表中所有的数据
    
    - 1. while + 索引 + 计数器
    
      2. 迭代器,对 某种对象(str/list/tuple/dict/set类创建的对象)-可迭代对象中的元素进行逐一获取 
    
         表象:具有_ _ next _ _方法且每次调用都获取可迭代对象中的元素(从前到后一个一个获取)。
    
         - 1. 先将某对象(如列表)转换成迭代器
    
              v1 = iter([11,22,33,44])
    
              v1 = [11,22,33,44]_ _ iter _ _() _
    
           2. 迭代器想要获取每个值:反复调用(val = v1._ _ next _ _())
    
              ```python
              v1 = [11,22,33,44]
              
              # 列表转换成迭代器
              v2 = iter(v1)
              result1 = v2.__next__()
              print(result1)
              result2 = v2.__next__()
              print(result2)
              result3 = v2.__next__()
              print(result3)
              result4 = v2.__next__()
              print(result4)
              result5 = v2.__next__()   # v1只有4个元素,第五次获取就会报错:StopIteration
              print(result5)
              
              v1 = "alex"
              v2 = iter(v1)
              while True:
                  try:
                      val = v2.__next__()
                      print(val)
                  except Exception as e:
                      break
              ```
    
           3. 直到报错:StopIteration错误,表示已经迭代完毕。
    
              ![](https://img2018.cnblogs.com/blog/1646753/201907/1646753-20190719213324918-1325127417.png)
    
           4. 如何判断一个对象是否是可迭代对象:内部是否有_ _ next _ _方法。
    
      3. for循环:
    
         ```python
         v1 = [11,22,33,44]
         
         # 1.内部会将v1转换成迭代器
         # 2.内部反复执行 迭代器.__next__()
         # 3.取完不报错
         for item in v1:
             print(item)
         ```
    
    ### 3 可迭代对象
    
    - 1. 内部具有_ _ iter _ _()方法且返回一个迭代器
    
         ```python
         v1 = [11,22,33,44]
         result = v1.__iter__()
         ```
    
      2. 可以被for循环的
  • 相关阅读:
    CSharpGL(36)通用的非托管数组排序方法
    CSharpGL(35)用ViewPort实现类似3DMax那样的把一个场景渲染到4个视口
    CSharpGL(34)以从零编写一个KleinBottle渲染器为例学习如何使用CSharpGL
    CSharpGL(33)使用uniform块来优化对uniform变量的读写
    CSharpGL(32)矩阵与四元数与角度旋转轴的相互转换
    CSharpGL(31)[译]OpenGL渲染管道那些事
    CSharpGL(30)用条件渲染(Conditional Rendering)来提升OpenGL的渲染效率
    Go如何使用数据库、缓存
    Go内置常用包
    从零开始基于go-thrift创建一个RPC服务
  • 原文地址:https://www.cnblogs.com/yangjie0906/p/11215825.html
Copyright © 2020-2023  润新知