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循环的
posted @ 2019-08-24 16:13  一直努力的小羊  阅读(209)  评论(0编辑  收藏  举报