Python笔记:Python装饰器

Posted

tags:

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

参考技术A

装饰器是通过装饰器函数修改原函数的一些功能而不需要修改原函数,在很多场景可以用到它,比如① 执行某个测试用例之前,判断是否需要登录或者执行某些特定操作;② 统计某个函数的执行时间;③ 判断输入合法性等。合理使用装饰器可以极大地提高程序的可读性以及运行效率。本文将介绍Python装饰器的使用方法。

python装饰器可以定义如下:

输出:

python解释器将test_decorator函数作为参数传递给my_decorator函数,并指向了内部函数 wrapper(),内部函数 wrapper() 又会调用原函数 test_decorator(),所以decorator()的执行会先打印\'this is wrapper\',然后打印\'hello world\', test_decorator()执行完成后,打印 \'bye\' ,*args和**kwargs,表示接受任意数量和类型的参数。

装饰器 my_decorator() 把真正需要执行的函数 test_decorator() 包裹在其中,并且改变了它的行为,但是原函数 test_decorator() 不变。

一般使用如下形式使用装饰器:

@my_decorator就相当于 decorator = my_decorator(test_decorator) 语句。

内置装饰器@functools.wrap可用于保留原函数的元信息(将原函数的元信息,拷贝到对应的装饰器函数里)。先来看看没有使用functools的情况:

输出:

从上面的输出可以看出test_decorator() 函数被装饰以后元信息被wrapper() 函数取代了,可以使用@functools.wrap装饰器保留原函数的元信息:

输出:

装饰器可以接受自定义参数。比如定义一个参数来设置装饰器内部函数的执行次数:

输出:

Python 支持多个装饰器嵌套:

装饰的过程:

顺序从里到外:

test_decorator(\'hello world\') 执行顺序和装饰的过程相反。

输出:

类也可以作为装饰器,类装饰器主要依赖__call__()方法,是python中所有能被调用的对象具有的内置方法(python魔术方法),每当调用一个类的实例时,__call__()就会被执行一次。

下面的类装饰器实现统计函数执行次数:

输出:

下面介绍两种装饰器使用场景

统计函数执行所花费的时间

输出:

在使用某些web服务时,需要先判断用户是否登录,如果没有登录就跳转到登录页面或者提示用户登录:

--THE END--

Python 3 学习笔记----装饰器

一、定义

装饰器本质是函数,装饰其他函数,就是为其它函数添加附加功能

二、装饰器原则

1.不能修改被装饰的函数的源代码

2.不能修改被装饰的函数的调用方式

三、实现装饰器的必要知识

1.函数即是变量

 1 # def foo():
 2 #     print("in the foo")
 3 #     bar()    #bar未定义
 4 # foo()
 5 
 6 
 7 # def bar():
 8 #     print("int the bar")
 9 # def foo():
10 #     print("in the foo")
11 #     bar()
12 # foo()
13 
14 
15 # def foo():
16 #     print("in the foo")
17 #     bar()
18 # def bar():
19 #     print("int the bar")
20 # foo()
1 def foo():
2     print("in the foo")
3     bar()
4 foo()
5 def bar():  #在调用后定义不会执行
6     print("int the bar")

2.高阶函数(高阶函数的两种表达方式)

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

 1 import time
 2 
 3  def bar():
 4      time.sleep(3)
 5      print("in the bar")
 6 
 7  def test1(func):
 8      start_time = time.time()
 9      func()
10      stop_time = time.time()
11      print("the func run time is %s" %(stop_time-start_time))
12  test1(bar)

2.2返回值中包含函数名

 1 import time
 2 def bar():
 3     time.sleep(3)
 4     print("in the bar")
 5 def test2(func):
 6     print(func)
 7     return func#返回为内存地址
 8 
 9 #print(test2(bar))
10 # t=test2(bar)
11 # t() #run bar
12 bar=test2(bar)
13 bar() #返回的内存地址加上()就可以执行

3.嵌套函数

 1 x=0
 2 def a():
 3     x=1
 4     def b():
 5         x=2
 6         def c():
 7             x=3
 8             print(x)
 9         c()
10     b() #此处如果不执行b(),那么函数相当于什么都没干,因为没有print
11 a()

四、装饰器=高阶函数+嵌套函数

 1 import time
 2 
 3 def timer(func):  #timer(test)  func=test
 4     def deco():
 5         start_time = time.time()
 6         func()   #此处运行被装饰函数test
 7         stop_time = time.time()
 8         print("func run time is %s" %(stop_time-start_time))
 9     return deco  #返回deco的内存地址
10 
11 
12 @timer   #相当于timer=timer(test),装饰器永远放在被装饰的函数前
13 def test():
14     time.sleep(3)
15     print("this is test")
16 
17 test()

五、如果装饰器的函数中包含参数

 1 import time
 2 
 3 def timer(func):
 4     def deco(*args,**kwargs):  #*args,**kwargs代表参数不确定的意思
 5         start_time=time.time()
 6         func(*args,**kwargs)
 7         stop_time=time.time()
 8         print("in the run time is %s" %(stop_time-start_time))
 9     return deco
10 
11 @timer   # test2 = timer(test2) = deco    test2(name) = deco(name)
12 def test2(age,name,job):
13     time.sleep(1)
14     print("test2:",age,name,job)
15 
16 test2(23,"Irlo","seller")

六、装饰器的使用实例

假设为网页添加登陆验证

 1 user,pasd = "Irlo","12345"
 2 def auth(auth_type):
 3     print("auth func is",auth_type)
 4     def type(func):
 5         def wrapper():
 6             if auth_type == "local":
 7                 username = input("username:").strip()  #strip移除字符串首尾指定的字符(默认为空格)
 8                 password = input("password:").strip()
 9                 if user==username and pasd==password:
10                     print("\033[1;32;1mauthority of account\033[0m") #高亮显示的格式(\033[显示方式;前景色;背景色m)
11                     res=func()  #将结果赋值给一个变量才能在之后调用home有结果
12                     print("after authentication")
13                     return res  #如果不返回,相当于执行完就结束了,没有返回值是一个空值
14                 else:
15                     print(" invalid username or password ")
16             elif auth_type == "ldap":
17                 print("I just know local,fuck off")
18         return wrapper
19     return type
20 
21 def index():
22     print("welcome to index page")
23 
24 @auth(auth_type = "local")
25 def home():
26     print("welcome to home page")
27     return "from home"
28 
29 @auth(auth_type = "ldap")
30 def bbs():
31     print("welcome to bbs page")
32 
33 index()
34 print(home()) #调用home的时候相当于是调用wrapper
35 home()
36 bbs()

 

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

python笔记第九天 装饰器

python学习笔记之装饰器(语法糖)

安全牛学习笔记python装饰器

24Python装饰器笔记

Python笔记:Python装饰器

python笔记--装饰器