Python 装饰器的使用

Python 装饰器的使用

一、基本概念:

装饰器本质上是一个Python函数或类,可以让其他函数或类在不需要做任务代码修改的前提下增加额外的功能,装饰器的返回值也是一个函数或类对象

二、使用场景:

1.插入日志

2.性能测试

3.事务处理

4.缓存机制

5.权限校验

6.路由分发等

三、简单使用:

需求:性能测试,记录每个函数处理的时间

import time

def process_time(func):
    """写一个处理时间的函数:"""

	# 记录处理func()函数前的时间
    start_time = time.time()
    func()
	# 记录处理func()函数后的书简
    end_time = time.time()
	# 做差值, 就是这个func()函数的处理时间
    result = end_time - start_time
	print 'time is %s s' % result


def func():
    """简单的函数"""
    time.sleep(5)
    print '___1.我先执行__'


# 将func 函数当作参数进行传入到process_time函数中, 进行处理, 获取func这个函数的处理时间
process_time(func)

# 输出结果如下:
___1.我先执行__
time is 5.00099992752 s

以上栗子,可以实现我们的需求,可是如果有func2(), func3()很多函数都需要此功能,我们还需要多次调用process_time()函数,传入不同的参数,这样做肯定不符合Python的优雅,下面开始进入简单装饰器的使用

import time

def decorator(func):
    """装饰器函数"""
    def wrapper():
        start_time = time.time()
        func()
        end_time = time.time()
        result = end_time - start_time
        print 'time is %s s' % result
        return result
    return wrapper

@decorator
def func():
    """简单的函数"""
    time.sleep(2)
    print '___1.我先执行__'

print func()

# 输出结果如下:
___1.我先执行__
time is 2.0 s
2.0

注意:@符号,在Python中叫语法糖,使用语法糖,同等于func = decorator(func)的使用

带有参数的装饰器

import time

def decorator(func):
    """装饰器函数, 带有参数"""
    def wrapper(*args):  # 注意有参数时, 需要传递*args, 参数
        start_time = time.time()
        ret_add = func(*args)  # 同理
        end_time = time.time()
        result = end_time - start_time
        print 'time is %s s' % result
        return ret_add  # 接收的是func(x, y) 函数的返回值, 结果为5
    return wrapper

@decorator
def func(x, y):
    """该函数有2个参数"""
    time.sleep(2)
    print '___1.我先执行__'
    return x + y

print func(2, 3)

# 输出结果如下:
___1.我先执行__
time is 2.0 s
5

带有不定长参数的装饰器

import time

def decorator(func):
    """装饰器函数, 带有参数"""
    def wrapper(*args, **kwargs):  # 注意传入不定长参数时, 需要加**kwargs
        start_time = time.time()
        ret_add = func(*args, **kwargs)  # 同理
        end_time = time.time()
        result = end_time - start_time
        print 'time is %s s' % result
        return ret_add  # 接收的是func(x, y, 2) 函数的返回值, 结果为 25
    return wrapper

@decorator
def func(x, y, z):
    """该函数有2个参数"""
    time.sleep(2)
    print '___1.我先执行__'
    return x + y + z


print func(2, 3, z=20)

# 输出结果如下:
___1.我先执行__
time is 2.0 s
25

多个装饰器:

import time


def decorator1(func):
    """装饰器函数1, 带有参数"""
    print '___进入装饰器1___'

    def wrapper(*args, **kwargs):
        start_time = time.time()
        ret_add = func(*args, **kwargs)
        print '___执行完装饰器1___'
        end_time = time.time()
        result = end_time - start_time
        return ret_add
    return wrapper


def decorator2(func):
    """装饰器函数2, 带有参数"""
    print '___进入装饰器2___'

    def wrapper(*args, **kwargs):
        start_time = time.time()
        ret_add = func(*args, **kwargs)
        print '___执行完装饰器2___'
        end_time = time.time()
        result = end_time - start_time
        return ret_add
    return wrapper


@decorator1
@decorator2
def func(x, y, z):
    """该函数有2个参数"""
    time.sleep(2)
    print '___执行函数__'
    return x + y + z


print func(2, 3, z=20)
# 输出结果如下:
___进入装饰器2___
___进入装饰器1___
___执行函数__
___执行完装饰器2___
___执行完装饰器1___
25

它执行顺序是从里到外,最先调用最里层的装饰器,最后调用最外层的装饰器

注意:相当于func = decorator1(decorator2(func))

使用装饰器类:主要依靠类的__ call __方法,当使用@形式将装饰器附加到函数上时,就会调用此方法:

class Dog(object):
    
    def __init__(self, func):
        self._func = func

    def __call__(self, *args, **kwargs):
        print '使用__call__方法前'
        self._func()
        print '使用__call__方法后'

@Dog  
def func():
    print '执行一个简单函数'

func()

# 输出结果如下:
使用__call__方法前
执行一个简单函数
使用__call__方法后

猜你喜欢

转载自blog.csdn.net/Fe_cow/article/details/94437243