## 生成器
- 生成器是用来创建Python序列的一个对象
- 通常生成器是为迭代器产生数据的
- 例如range()函数就是一个生成器
- 每次迭代生成器时,它都会记录上一次调用的位置,并返回下一个值,这使程序不需要创建和存储完整的序列
## 生成器函数
- 生成器函数与普通函数类似,但它的返回值使用yield语句,而不是return
1 def my_range(start=0, last=10, step=1):2 number =start3 while number <4 yieldnumber5 number>
7 my_range #是一个普通函数
8 #
9
10 my_range() #返回一个生成器对象
11 #
12
13 list(my_range(1, 10))14 #[1, 2, 3, 4, 5, 6, 7, 8, 9]
## 装饰器
- 装饰器的作用在于在不改变原有代码结构的前提下,对原有代码的功能进行补充扩展
- 装饰器的本质上是接受函数为参数的高阶函数,它把一个函数作为参数输入并且返回一个功能拓展后的新函数
1 #装饰器函数,为函数添加两条语句
2 defdeco(fn):3 def new_func(*args): #内部函数的参数需要与传入的fn的参数相同
4 print("执行函数:{0}".format(fn.__name__))5 result = fn(*args)6 print("函数执行结果:{0}".format(result))7 returnresult8 returnnew_func9
10
11 @deco #使用@装饰函数名,使用装饰器之后,add实际上已经指向了doco函数返回的新函数
12 def add(*args):13 print("我是核心代码,可不能改动我")14 result =015 for n inargs:16 result +=n17 returnresult18
19
20 add(1, 2, 3, 4)21 """
22 执行结果:23 执行函数:add24 我是核心代码,可不能改动我25 函数执行结果:1026 """
- 一个函数可以有多个装饰器
- 最靠近函数的装饰器会先执行,然后一次向上执行装饰器
1 defcount_param(fn):2 def new_func(*args):3 amount =len(args)4 fn(*args)5 print("参数个数为:{0}".format(amount))6 returnamount7 returnnew_func8
9
10 @count_param11 @deco12 def add(*args):13 print("我是核心代码,可不能改动我")14 result =015 for n inargs:16 result +=n17 returnresult18
19
20 add(1, 2, 3, 4)21 """
22 执行结果:23 执行函数:add24 我是核心代码,可不能改动我25 函数执行结果:1026 参数个数为:427 """
- 如果decorator本身需要传入参数,那就需要编写一个返回decorator的高阶函数
1 importtime2
3
4 deflog(now_time):5 defdeco(fn):6 def new_func(*args, **kwargs):7 print(now_time)8 return fn(*args, **kwargs)9 returnnew_func10 returndeco11
12
13 @log(time.asctime(time.localtime(time.time())))14 def add(*args):15 print("我是核心代码,可不能改动我")16 result =017 for n inargs:18 result +=n19 returnresult20
21
22 add(1, 2, 3, 4)23 """
24 执行结果:25 函数开始时间:Sun Jul 1 15:30:14 201826 我是核心代码,可不能改动我27 """
- 此时打印add函数的__name__属性发现:
print("核心函数名:{0}".format(add.__name__))"""输出:
核心函数名:new_func"""
- 这表明虽然装饰器表面上并没有改变核心函数的内容,但实际上还是对核心函数的属性进行了修改,所以还需要将核心函数的__name__属性复制到新函数
1 importtime2
3
4 deflog(now_time):5 defdeco(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 returnnew_func12 returndeco13
14
15 @log(time.asctime(time.localtime(time.time())))16 def add(*args):17 print("我是核心代码,可不能改动我")18 result =019 for n inargs:20 result +=n21 returnresult22
23
24 add(1, 2, 3, 4)25 print("核心函数名:{0}".format(add.__name__))26 """
27 执行结果:28 Sun Jul 1 15:43:00 201829 我是核心代码,可不能改动我30 核心函数名:add31 """
- 在functools里面有一个专门的函数处理这个问题
1 importtime2 importfunctools3
4
5 deflog(now_time):6 defdeco(fn):7 @functools.wraps(fn) #在新的函数上添加装饰器,修改新函数的__name__属性
8 def new_func(*args, **kwargs):9 print(now_time)10 return fn(*args, **kwargs)11 returnnew_func12 returndeco13
14
15 @log(time.asctime(time.localtime(time.time())))16 def add(*args):17 print("我是核心代码,可不能改动我")18 result =019 for n inargs:20 result +=n21 returnresult22
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 核心函数名:add31 “”“
本文参考:
[美]Bill Lubanovic 《Python语言及其应用》
https://www.liaoxuefeng.com 廖雪峰的官方网站
4>