Python装饰器

在学习函数装饰器前,首先要学习高阶函数+函数嵌套+闭包

  •  高阶函数

只要满足下列条件之一就是一个高阶函数:

1.函数接收的参数是一个函数名

2.函数的返回值是一个函数名

第一种情况:接收的参数是一个函数名

1 def foo1(name):
2     return name()
3 def foo2():
4     print('this is foo2')
5 
6 foo1(foo2)
运行结果:
##this is foo2

第二种情况:返回值是一个函数名

def foo1():
    return 'this is foo1'

def foo2():
    print('this is foo2')
    return foo1

func = foo2()
print(func)
print(func())

运行结果:

# this is foo2
# <function foo1 at 0x000000000216E378>
# this is foo1
  • 函数嵌套

什么是函数嵌套?

在一个函数里嵌套一个子函数就是一个函数嵌套。

def father(name):
    def son():
        print('这个名字是:%s'%name)
        def grandson():
            name = '我自己'
            print('这个名字是 :%s'%name)
        grandson()
    son()
father('weibo')

运行结果:

1 # 这个名字是:weibo
2 # 这个名字是 :我自己
  • 闭包

概念:实质上就是一个函数嵌套,而闭包指的是函数作用域(作用的变量)

装饰器

什么是装饰器呢?

装饰器本质上就是一个函数,功能就是在不改变原有函数以及原有函数的调用方式的基础上为原有函数添加新功能

装饰器:高阶函数+函数嵌套+闭包

原则:

1,不改变被修饰函数的源代码

2,不改变被修饰函数的调用方式

一个简单的装饰器架子:


##  一个简单的装饰器架子
## 需求:在不改变test源代码和调用方式的前提下为test函数添加一个计时的功能
import time

def
decorator_func(func): def functor(): time_start = time.time() func() time_end = time.time() print('运行test函数所用的时间是:%s'%(time_end-time_start)) return functor @decorator_func ## 语法塘:相当于 test = decorator_func(test) def test(): time.sleep(3)
   print('test函数')
return '这是test的内容' res = test() ## res = decorator_func(test)()-->functor() print(res)

运行结果:

1 # test函数
2 # 运行test函数所用的时间是:3.000171422958374 3 # None

上述的test()函数不能带有返回值,因为在装饰器函数中没有接收到,下面接收这个return值

 1 import time
 2 
 3 def decorator_func(func):
 4     def functor():
 5         time_start = time.time()
 6         test1 = func()      ##  这里就是将func()运行,并把return的值赋值给test1
 7         time_end = time.time()
 8         print('运行test函数所用的时间是:%s'%(time_end-time_start))
 9         return test1
10     return functor
11 
12 @decorator_func     ##  语法塘:相当于 test = decorator_func(test)
13 def test():
14     time.sleep(3)
15     return '这是test内容的'
16 
17 res = test()        ##  res = decorator_func(test)()-->functor()
18 print(res)

运行结果:

1 # test函数
2 # 运行test函数所用的时间是:3.000171661376953
3 # 这是test内容的

被修饰函数加入参数:

 1 import time
 2 
 3 def decorator_func(func):
 4     def functor(*args,**kwargs):        ## 这里加入参数
 5         time_start = time.time()
 6         test1 = func(*args,**kwargs)      ##  这里就是将func()运行,并把return的值赋值给test1
 7         time_end = time.time()
 8         print('运行test函数所用的时间是:%s'%(time_end-time_start))
 9         return test1
10     return functor
11 
12 @decorator_func     ##  语法塘:相当于 test = decorator_func(test)
13 def test(a,b,c):
14     time.sleep(3)
15     print('test函数')
16     print('打印出%s中的%s中的%s'%(a,b,c))
17     return '这是test内容的'
18 
19 res = test('test1','test2','test3')        ##  res = decorator_func(test)()-->functor()
20 print(res)    

运行结果:

1 # test函数
2 # 打印出test1中的test2中的test3
3 # 运行test函数所用的时间是:3.000171422958374
4 # 这是test内容的
  • 注意:

被装饰器函数修饰过的函数本质上已经是另一个函数了,实际开发中有时候会给我们带来困扰,所以可以加@wraps修饰,将函数名转为原来的函数名,消除这种影响。

例子:

import time
from functools import wraps
def decorator_func(func): @wraps def functor(*args,**kwargs): ## 这里加入参数 time_start = time.time() test1 = func(*args,**kwargs) ## 这里就是将func()运行,并把return的值赋值给test1 time_end = time.time() print('运行test函数所用的时间是:%s'%(time_end-time_start)) return test1 return functor @decorator_func ## 语法塘:相当于 test = decorator_func(test) def test(a,b,c): time.sleep(3) print('test函数') print('打印出%s中的%s中的%s'%(a,b,c)) return '这是test内容的' res = test('test1','test2','test3') ## res = decorator_func(test)()-->functor() print(res)

扩展:多个装饰器一起用:

 1 import time
 2 
 3 def decorator_func1(func):
 4     def functor(*args,**kwargs):
 5         print('开始运行装饰器1')
 6         time_start = time.time()
 7         test1 = func(*args,**kwargs)      
 8         time_end = time.time()
 9         print('运行test函数所用的时间是:%s'%(time_end-time_start))
10         print('停止运行装饰器1')
11         return test1
12     return functor
13 
14 def decorator_func2(func):
15     def functor(*args,**kwargs):
16         print('开始运行装饰器2')
17         res = func(*args,**kwargs)
18         print('装饰器2运行结束')
19         return res
20     return functor
21 
22 @decorator_func1     
23 @decorator_func2        ##  这里的语法塘相当于: res = decorator_func1(decorator_func2(test('test1','test2','test3')))
24 def test(a,b,c):
25     time.sleep(3)
26     print('test函数')
27     print('打印出%s中的%s中的%s'%(a,b,c))
28     return '这是test内容的'
29 
30 res = test('test1','test2','test3')        
31 print(res)

 运行结果:

1 # 开始运行装饰器1
2 # 开始运行装饰器2
3 # test函数
4 # 打印出test1中的test2中的test3
5 # 装饰器2运行结束
6 # 运行test函数所用的时间是:3.000171661376953
7 # 停止运行装饰器1
8 # 这是test内容的

Python内置装饰器

在Python中有三个内置的装饰器,都是跟class相关的:staticmethod、classmethod 和property。

  • staticmethod 是类静态方法,其跟成员方法的区别是没有 self 参数,并且可以在类不进行实例化的情况下调用
  • classmethod 与成员方法的区别在于所接收的第一个参数不是 self (类实例的指针),而是cls(当前类的具体类型)
  • property 是属性的意思,表示可以通过通过类实例直接访问的信息
原文地址:https://www.cnblogs.com/maoxinjueluo/p/12581062.html