Python生成器、装饰器

匿名 (未验证) 提交于 2019-12-02 22:56:40

## 生成器
  - 生成器是用来创建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 “”“

本文参考:

  [美]Bill Lubanovic 《Python语言及其应用》

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!