zoukankan      html  css  js  c++  java
  • Python生成器、装饰器

    ## 生成器
      - 生成器是用来创建Python序列的一个对象
      - 通常生成器是为迭代器产生数据的
      - 例如range()函数就是一个生成器
      - 每次迭代生成器时,它都会记录上一次调用的位置,并返回下一个值,这使程序不需要创建和存储完整的序列

    ## 生成器函数
      - 生成器函数与普通函数类似,但它的返回值使用yield语句,而不是return

     1 def my_range(start=0, last=10, step=1):
     2     number = start
     3     while number < last:
     4         yield number
     5         number += step
     6     
     7 my_range     # 是一个普通函数
     8 # <function my_range at 0x7efe3dbf2e18>
     9 
    10 my_range()   # 返回一个生成器对象
    11 # <generator object my_range at 0x7efe3daac360>
    12 
    13 list(my_range(1, 10))
    14 # [1, 2, 3, 4, 5, 6, 7, 8, 9]          

    ## 装饰器

      - 装饰器的作用在于在不改变原有代码结构的前提下,对原有代码的功能进行补充扩展
      - 装饰器的本质上是接受函数为参数的高阶函数,它把一个函数作为参数输入并且返回一个功能拓展后的新函数

     1 # 装饰器函数,为函数添加两条语句
     2 def deco(fn):
     3     def new_func(*args):  # 内部函数的参数需要与传入的fn的参数相同
     4         print("执行函数:{0}".format(fn.__name__))
     5         result = fn(*args)
     6         print("函数执行结果:{0}".format(result))
     7         return result
     8     return new_func
     9 
    10 
    11 @deco    # 使用@装饰函数名,使用装饰器之后,add实际上已经指向了doco函数返回的新函数
    12 def add(*args):
    13     print("我是核心代码,可不能改动我")
    14     result = 0
    15     for n in args:
    16         result += n
    17     return result
    18 
    19 
    20 add(1, 2, 3, 4)
    21 """
    22 执行结果:
    23     执行函数:add
    24     我是核心代码,可不能改动我
    25     函数执行结果:10
    26 """

        

        - 一个函数可以有多个装饰器

        - 最靠近函数的装饰器会先执行,然后一次向上执行装饰器

     1 def count_param(fn):
     2     def new_func(*args):
     3         amount = len(args)
     4         fn(*args)
     5         print("参数个数为:{0}".format(amount))
     6         return amount
     7     return new_func
     8 
     9 
    10 @count_param
    11 @deco
    12 def add(*args):
    13     print("我是核心代码,可不能改动我")
    14     result = 0
    15     for n in args:
    16         result += n
    17     return result
    18 
    19 
    20 add(1, 2, 3, 4)
    21 """
    22 执行结果:
    23     执行函数:add
    24     我是核心代码,可不能改动我
    25     函数执行结果:10
    26     参数个数为:4
    27 """

        - 如果decorator本身需要传入参数,那就需要编写一个返回decorator的高阶函数

     1 import time
     2 
     3 
     4 def log(now_time):
     5     def deco(fn):
     6         def new_func(*args, **kwargs):
     7             print(now_time)
     8             return fn(*args, **kwargs)
     9         return new_func
    10     return deco
    11 
    12 
    13 @log(time.asctime(time.localtime(time.time())))
    14 def add(*args):
    15     print("我是核心代码,可不能改动我")
    16     result = 0
    17     for n in args:
    18         result += n
    19     return result
    20 
    21 
    22 add(1, 2, 3, 4)
    23 """
    24 执行结果:
    25     函数开始时间:Sun Jul  1 15:30:14 2018
    26     我是核心代码,可不能改动我
    27 """

      - 此时打印add函数的__name__属性发现:

    print("核心函数名:{0}".format(add.__name__))
    """
    输出:
        核心函数名:new_func
    """

      

      - 这表明虽然装饰器表面上并没有改变核心函数的内容,但实际上还是对核心函数的属性进行了修改,所以还需要将核心函数的__name__属性复制到新函数

     1 import time
     2 
     3 
     4 def log(now_time):
     5     def deco(fn):
     6         def new_func(*args, **kwargs):
     7             # 将原函数的__name__属性复制到新函数
     8             new_func.__name__ = fn.__name__
     9             print(now_time)
    10             return fn(*args, **kwargs)
    11         return new_func
    12     return deco
    13 
    14 
    15 @log(time.asctime(time.localtime(time.time())))
    16 def add(*args):
    17     print("我是核心代码,可不能改动我")
    18     result = 0
    19     for n in args:
    20         result += n
    21     return result
    22 
    23 
    24 add(1, 2, 3, 4)
    25 print("核心函数名:{0}".format(add.__name__))
    26 """
    27 执行结果:
    28     Sun Jul  1 15:43:00 2018
    29     我是核心代码,可不能改动我
    30     核心函数名:add
    31 """    

      - 在functools里面有一个专门的函数处理这个问题

     1 import time
     2 import functools
     3 
     4 
     5 def log(now_time):
     6     def deco(fn):
     7         @functools.wraps(fn)      # 在新的函数上添加装饰器,修改新函数的__name__属性
     8         def new_func(*args, **kwargs):
     9             print(now_time)
    10             return fn(*args, **kwargs)
    11         return new_func
    12     return deco
    13 
    14 
    15 @log(time.asctime(time.localtime(time.time())))
    16 def add(*args):
    17     print("我是核心代码,可不能改动我")
    18     result = 0
    19     for n in args:
    20         result += n
    21     return result
    22 
    23 
    24 add(1, 2, 3, 4)
    25 print("核心函数名:{0}".format(add.__name__))
    26 ”“”
    27 执行结果:
    28     Sun Jul  1 15:48:10 2018
    29     我是核心代码,可不能改动我
    30     核心函数名:add
    31 “”“

      - 类装饰器 

     1 class Test(object):
     2     def __init__(self, fn):
     3         self.fn = fn
     4 
     5     # 重写__call__函数,使实例能够像函数一样调用
     6     def __call__(self, *args, **kwargs):
     7         print("这是基于类的修饰")
     8         return self.fn(*args, **kwargs)
     9 
    10 
    11 @Test
    12 def core_func(a, b):
    13     return a + b
    14 
    15 
    16 print(core_func(2, 3))
    17 """
    18 输出:
    19     这是基于类的修饰
    20     5
    21 """

      - 类装饰器带参数

     1 import datetime
     2 import functools
     3 
     4 
     5 class Test(object):
     6     def __init__(self, log):
     7         self.log = log
     8 
     9     # 重写__call__函数,使实例能够向函数一样调用
    10     def __call__(self, fn):
    11         @functools.wraps(fn)    # 同样在这里使用functools.wraps(),将原函数__name__属性复制到新函数
    12         def wrapper(*args, **kwargs):
    13             print(self.log)
    14             print("执行函数:%s" % fn.__name__)
    15             return fn(*args, **kwargs)
    16         return wrapper
    17 
    18 
    19 @Test(datetime.datetime.now())
    20 def core_func(a, b):
    21     return a + b
    22 
    23 
    24 @Test(datetime.datetime.now())
    25 def say_hi():
    26     print("Hi")
    27 
    28 
    29 print(core_func(2, 3))
    30 print(core_func.__name__)   # 输出:core_func
    31 say_hi()
    32 print(say_hi.__name__)      # 输出:say_hi
    33 """
    34 输出:
    35     2018-07-02 10:55:27.258637
    36     执行函数:core_func
    37     5
    38     core_func
    39     2018-07-02 10:55:27.258696
    40     执行函数:say_hi
    41     Hi
    42     say_hi
    43 """

    本文参考:

      [美]Bill Lubanovic 《Python语言及其应用》
      https://www.liaoxuefeng.com 廖雪峰的官方网站 

  • 相关阅读:
    Atitit 趋势管理之道 attilax著
    Atitit 循环处理的新特性 for...else...
    Atitit 2017年的技术趋势与未来的大技术趋势
    atitit 用什么样的维度看问题.docx 如何了解 看待xxx
    atitit prj mnrs 项目中的几种经理角色.docx
    Atitit IT办公场所以及度假村以及网点以及租房点建设之道 attilax总结
    Atitit 工具选型的因素与方法 attilax总结
    Atitit.团队文化建设影响组织的的一些原理 法则 定理 效应 p826.v4
    Atiitt 管理方面的误区总结 attilax总结
    Atitit 未来趋势把控的书籍 attilax总结 v3
  • 原文地址:https://www.cnblogs.com/hycstar/p/9250403.html
Copyright © 2011-2022 走看看