装饰器

Posted bit-taozhen

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了装饰器相关的知识,希望对你有一定的参考价值。

定义:

  器字代表函数,装饰器本质是函数;装饰:装饰其他函数,就是为其他函数添加附加功能

原则:

  1.不能修改被装饰函数的源代码(在不修改被装饰函数源代码的情况下为其添加功能)

  2.不能修改被装饰的函数的调用函数,被装饰函数不知道被装饰了

实现装饰器需要了解:

  1.函数及变量:内存存储函数方式与存储变量一样:内存中存储函数体,再指向函数名

技术分享图片

  2.高阶函数

a.把一个函数名当作实参传给另外个函数(在不修改被装饰函数源代码的情况下为其添加功能)

b.返回值中包含函数名(不修改函数的调用方式)

 1 import time
 2 def bar():#bar是这个函数的门牌号
 3     time.sleep(2)
 4     print(in the bar)
 5 def test1(func):#不是装饰器,是因为函数的调用方式test1(bar)被更改了
 6     start_time=time.time()
 7     func()
 8     stop_time=time.time()
 9     print(the func fun time is %s % (stop_time-start_time))
10 
11 test1(bar) #func=bar

 运行结果:

  技术分享图片

 1 import time
 2 def bar():#bar是这个函数的门牌号
 3     time.sleep(2)
 4     print(in the bar)
 5 
 6 def test2(func):
 7     print(func)
 8     return func
 9 
10 print(test2(bar))
11 print(--------------------)
12 bar=test2(bar)
13 print(--------------------)
14 bar()

运行结果:

技术分享图片

  3.嵌套函数:在已定义的函数内部再定义函数

1 def foo():
2     print(in the foo)
3     def bar():#bar具有局部变量的特性
4         print(in the bar)

 

通过高阶函数和嵌套函数实现装饰器功能:

 1 import time
 2 
 3 def timer(func):#在被装饰函数之外嵌套装饰器函数,添加装饰功能
 4     def deco(*args,**kwargs):#不固定参数参数
 5         start_time=time.time()
 6         result=func(*args,**kwargs)#被装饰的函数在这运行
 7         stop_time=time.time()
 8         print(the func run time is %s % (stop_time-start_time))
 9 
10         return result#加入了返回值
11     return deco#timer这个函数返回了deco函数的地址
12 
13 @timer#@timer等于test1=timer(test1):返回了deco函数的内存地址赋给了test1,此时test1是新的test1,这时的test1已经有了装饰器的功能
14 def test1():
15     time.sleep(3)
16     print(in the test1)
17 
18 @timer#test2=timer(test2),deco=test2
19 def test2(name):
20     time.sleep(3)
21     print(test2:,name)
22     print(in the test2)
23     return from test2#加入了返回,装饰器内的函数也要加返回
24 
25 test1()
26 print(-----------------)
27 print(test2(tao))#print打印函数的返回值

运行结果:

技术分享图片

  所以说,装饰器就是将被装饰函数在装饰器函数内执行,再将装饰器函数赋予被装饰函数名,之后再执行被装饰函数时就相当于执行了装饰器函数,即在没有改变被装饰函数的源代码和调用方式的情况下,实现了装饰的功能。

 

实现加入参数的装饰器:

 1 user,passwd=Tao,abc
 2 def auth(auth_type):#与未加参数的装饰器区别:装饰器多加了一个参数,要多嵌套一层函数;auth返回的仍是wrapper这个函数
 3     def outer_wrapper(func):#注意加入的参数和func的位置
 4         def wrapper(*args, **kwargs):#auth函数返回out_wrapper,out_wrapper函数返回wrapper,所以auth函数返回的仍是wrapper这个函数
 5 
 6             #判断参数
 7             if auth_type==local:
 8                 username = input(username:).strip()
 9                 password = input(passwd:).strip()
10 
11                 if user == username and passwd == password:
12                     print(欢迎)
13                     res = func(*args, **kwargs)  #当被装饰函数有返回值时
14                     return res
15                 else:
16                     exit(错误)
17 
18             #判断参数
19             elif auth_type==ldap:
20                 print(ldap无法实现)
21 
22         return wrapper
23 
24     return outer_wrapper
25 
26 
27 
28 def index():
29     print(welcome to index page)
30 
31 @auth(auth_type=local)#auth返回了wrapper这个函数赋给了home
32 def home():
33     print(welcome to home page)
34     return "from home" #加入了返回,装饰器内的函数也要加返回
35 
36 @auth(auth_type=ldap)#auth返回了wrapper这个函数赋给了bbs
37 def bbs():
38     print(welcome to bbs page)
39 
40 index()
41 print(--------------------)
42 print(home())#打印函数的返回值即from home
43 print(--------------------)
44 bbs()

运行结果:

技术分享图片

 

以上是关于装饰器的主要内容,如果未能解决你的问题,请参考以下文章

Python面向对象学习之八,装饰器

thymeleaf 片段渲染后重新加载 javascript

代码缺乏装饰?使用ts装饰器来装饰你的代码

代码缺乏装饰?使用ts装饰器来装饰你的代码

代码缺乏装饰?使用ts装饰器来装饰你的代码

代码缺乏装饰?使用ts装饰器来装饰你的代码