python3 装饰器_python3 装饰器全解

本章结构:

1.理解装饰器的前提准备

2.装饰器:无参/带参的被装饰函数,无参/带参的装饰函数

3.装饰器的缺点

4.python3的内置装饰器

5.本文参考

理解装饰器的前提:1.所有东西都是对象(函数可以当做对象传递) 2.闭包

闭包的概念:

1)函数嵌套

2)内部函数使用外部函数的变量

3)外部函数的返回值为内部函数

下面写一个最为简单的闭包的例子:

1 deftest(name):2 deftest_in():3 print(name)4 returntest_in5

6 func = test('whyz')7 func()

装饰器的原型:

1 importtime2 defshowtime(func):3 defwrapper():4 start_time =time.time()5 func()6 end_time =time.time()7 print('spend is {}'.format(end_time -start_time))8

9 returnwrapper10

11 deffoo():12 print('foo..')13 time.sleep(3)14

15 foo =showtime(foo)16 foo()

不带参数的装饰器:(装饰器,被装饰函数都不带参数)

1 importtime2 defshowtime(func):3 defwrapper():4 start_time =time.time()5 func()6 end_time =time.time()7 print('spend is {}'.format(end_time -start_time))8

9 returnwrapper10

11 @showtime #foo = showtime(foo)

12 deffoo():13 print('foo..')14 time.sleep(3)15

16 @showtime #doo = showtime(doo)

17 defdoo():18 print('doo..')19 time.sleep(2)20

21 foo()22 doo()

带参数的被装饰的函数

1 importtime2 defshowtime(func):3 defwrapper(a, b):4 start_time =time.time()5 func(a,b)6 end_time =time.time()7 print('spend is {}'.format(end_time -start_time))8

9 returnwrapper10

11 @showtime #add = showtime(add)

12 defadd(a, b):13 print(a+b)14 time.sleep(1)15

16 @showtime #sub = showtime(sub)

17 defsub(a,b):18 print(a-b)19 time.sleep(1)20

21 add(5,4)22 sub(3,2)

带参数的装饰器(装饰函数),

实际是对原有装饰器的一个函数的封装,并返回一个装饰器(一个含有参数的闭包函数),

当使用@time_logger(3)调用的时候,Python能发现这一层封装,并将参数传递到装饰器的环境去

1 importtime2 def time_logger(flag =0):3 defshowtime(func):4 defwrapper(a, b):5 start_time =time.time()6 func(a,b)7 end_time =time.time()8 print('spend is {}'.format(end_time -start_time))9

10 ifflag:11 print('将此操作保留至日志')12

13 returnwrapper14

15 returnshowtime16

17 @time_logger(2) #得到闭包函数showtime,add = showtime(add)

18 defadd(a, b):19 print(a+b)20 time.sleep(1)21

22 add(3,4)

类装饰器:一般依靠类内部的__call__方法

1 importtime2 classFoo(object):3 def __init__(self, func):4 self._func =func5

6 def __call__(self):7 start_time =time.time()8 self._func()9 end_time =time.time()10 print('spend is {}'.format(end_time -start_time))11

12 @Foo #bar = Foo(bar)

13 defbar():14 print('bar..')15 time.sleep(2)16

17 bar()

使用装饰器的缺点:

1.位置错误的代码->不要在装饰器之外添加逻辑功能

2.不能装饰@staticmethod 或者 @classmethod已经装饰过的方法

3.装饰器会对原函数的元信息进行更改,比如函数的docstring,__name__,参数列表:

下面对装饰器第第三个缺点进行剖析,

1 importtime2 defshowtime(func):3 defwrapper():4 start_time =time.time()5 func()6 end_time =time.time()7 print('spend is {}'.format(end_time -start_time))8

9 returnwrapper10

11 @showtime #foo = showtime(foo)

12 deffoo():13 print('foo..')14 time.sleep(3)15

16 defdoo():17 print('doo..')18 time.sleep(2)19

20 print(foo.__name__)21 print(doo.__name__)

结果为:

wrapper

doo

由此可以看出,装饰器会对原函数的元信息进行更改,可以使用wraps,进行原函数信息的添加

注解:wraps本身也是一个装饰器,他能把函数的元信息拷贝到装饰器函数中使得装饰器函数与原函数有一样的元信息

以下是一个wraps的例子:

1 importtime2 from functools importwraps3 defshowtime(func):4

5 @wraps(func)6 defwrapper():7 start_time =time.time()8 func()9 end_time =time.time()10 print('spend is {}'.format(end_time -start_time))11

12 returnwrapper13

14 @showtime #foo = showtime(foo)

15 deffoo():16 print('foo..')17 time.sleep(3)18

19 defdoo():20 print('doo..')21 time.sleep(2)22

23 print(foo.__name__)24 print(doo.__name__)

结果为:

foo

doo

常用的内置装饰器:1.staticmethod: 类似实现了静态方法 注入以后,可以直接 : 类名.方法

2.property:经过property装饰过的函数 不再是一个函数,而是一个property,类似实现get,set方法

1 @property2 defwidth(self):3 return self.__width

4

5 @width.setter6 defwidth(self, newWidth):7 self.__width = newWidth

3.classmethod: 与staticmethod很相似,貌似就只有这一点区别:

第一个参数需要是表示自身类的 cls 参数,

可以来调用类的属性,类的方法,实例化对象等。

本文参考:

1.https://www.cnblogs.com/vamei/archive/2013/02/16/2820212.html

2.https://www.cnblogs.com/wupeiqi/articles/4980620.html

3.https://www.cnblogs.com/yuanchenqi/articles/5830025.html

4.https://blog.csdn.net/mdzzname/article/details/78702440

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值