装饰器

装饰器是由函数去生成的,用于装饰某个函数或者方法或者类,他可以让这个函数在执行之前或者执行之后做一些操作

实例

定义一个函数func

#!/usr/bin/env python
# _*_ coding:utf-8 _*_

def func(arg):
    print(arg)

func("Hello World!")

执行脚本,输出的结果为

Hello World!

现在,要在执行func这个函数前后执行一些操作,就可以创建一个装饰器来实现

#!/usr/bin/env python
# _*_ coding:utf-8 _*_

# 创建一个装饰器函数,接受的参数arg参数就是func函数名
def decorator(func):

    def inner(*args,**kwargs):
        print("before exec func: ")
        ret = func(*args,**kwargs)
        print("after exec func: ")
        return ret
    return inner

# 如果要让某个函数使用装饰器,只需要在这个函数上面加上@装饰器名字
@decorator
def func(arg):
    print(arg)

func("Hello World!")

输出结果

before exec func:
Hello World!
after exec func:
实例2
import time
def timer(func):
  def deco():
    start_time = time.time()
    func()
    stop_time = time.time()
    print('the func run time is %s' % (stop_time - start_time))
  return deco

@timer
def test1():
  time.sleep(3)
  print('test1')

# @timer
# def test2(name):
#   print("test:", name)

test1()
# test2()

把注释内容取消注释, 会报错, 这是因为这个装饰器不支持参数, 后文会讲到带参数的装饰器.

多个装饰器装饰同一个函数

#!/usr/bin/env python
# _*_ coding:utf-8 _*_

def decorator1(func):
    def inner():
        print("decorator1 >>> start")
        ret = func()
        print("decorator1 >>> end")
        return ret
    return inner

def decorator2(func):
    def inner():
        print("decorator2 >>> start...")
        ret = func()
        print("decorator2 >>> end...")
        return ret
    return inner

@decorator1
@decorator2
def index():
    print("执行函数...")
index()

执行结果

➜  python_test python3 015-exercise-3.py
decorator1 >>> start
decorator2 >>> start...
执行函数...
decorator2 >>> end...
decorator1 >>> end

更多实例

#!/usr/bin/env python
# _*_ coding:utf-8 _*_

"""
函数装饰器
"""

def decorator(func):
    def wrapped(*args,**kwargs):
        return func(*args,**kwargs)
    return wrapped

@decorator
def func(a,b):
    return a + b

print(func(1,2))

"""
类装饰器
"""

class decorator:
    def __init__(self,func):
        self.func = func

    def __call__(self,*args,**kwargs):
        return self.func(*args,**kwargs)

@decorator
def func(a,b):
    return a + b

print(func(1,2))

"""
带参数的函数装饰器
"""

def parameter(a,b):
    print(a,b)

    def decorator(func):
        def wrapped(*args,**kwargs):
            return func(*args,**kwargs)
        return wrapped
    return decorator

@parameter(1,2)
def func(a,b):
    return a + b
print(func(10,20))

"""
带参数的类装饰器
"""

def parameter(a,b):
    print(a + b)

    class decorator:
        def __init__(self,func):
            self.func = func
        def __call__(self,*args,**kwargs):
            return self.func(*args,**kwargs)

    return decorator

@parameter(1,2)
def func(a,b):
    return a + b

print(func(10,20))

"""
带参数的类装饰器
"""

def parameter(a,b):
    print(a,b)

    def decorator(cls):
        class wrapped:
            def __init__(self,*args,**kwargs):
                self.cls = cls(*args,**kwargs)
            def __getattr__(self,item):
                return getattr(self.cls,item)
        return wrapped
    return decorator

@parameter(1,2)
class CLS:
    def __init__(self):
        self.a = 'a'

    def P(self,v):
        print(v)

obj = CLS()
print(obj.a)
obj.P('Hello')

"""
为函数中和类中的方法添加装饰器
"""

def Call(aClass):
    calls = 0

    def onCall(*args,**kwargs):
        nonlocal calls
        calls +=1
        print('call %s to %s' % (calls,func.__name__))
        return aClass(*args,**kwargs)
    return onCall

@Call
def func(a,b):
    return a + b

print(func(1,2))

class CLS:
    def __init__(self):
        self.a = 'a'
    @Call
    def b(self):
        return self.a

obj = CLS()
print(obj.b())

执行结果

➜  python_test python3 015-exercise-4.py
3
3
1 2
30
3
30
1 2
a
Hello
call 1 to onCall
3
call 1 to onCall
a