[Python] 装饰器

本质

一种语法糖。
现有一个函数decorator(fun)

def decorator(fun):
	def wrapper():
		...
		fun()
		...
	return wrapper

那么

def fun():
	...

fun = decorator(fun)

等价于

@decorator
def fun():
	...

用法

装饰器调用顺序

装饰器是可以叠加使用的,调用顺序与使用 @ 声明的顺序相反。
##被装饰的函数带参数
前面的例子中,被装饰函数的本身没有参数。如果被装饰函数需要支持参数,那么装饰器的内嵌函数需要支持同样的参数。如果在decorator()wrapper()之间加入其它语句,它们会在使用decorator()装饰其他函数时执行一次。

def decorator(fun):
	def wrapper(a):
		...
		fun(a)
		...
	return wrapper

@decorator
def fun(a):
	...

装饰器带参数

def decorator(flag=True):
    if flag:
        def _decorator(fun):  # 函数有参数
            def wrapper(*args, **kwargs):
                print("This is wrapper")
                fun(*args, **kwargs)
            return wrapper
    else:
        def _decorator(fun):  # 函数无参数
            def wrapper():
                print("This is wrapper")
                fun()
            return wrapper
    return _decorator


@decorator(flag=False)
def fun1():
    print("This is fun1")


@decorator()  # 这个括号不能省略
def fun2(a, b):
    print("This is fun2")
    print("a = " + str(a))
    print("b = " + str(b))

fun1()
print("")
fun2(13, 22)

装饰器带类参数

class Locker:
    def __init__(self):
        print("locker.__init__() should be not called.")

    @staticmethod
    def acquire():
        print("locker.acquire() called.(这是静态方法)")

    @staticmethod
    def release():
        print("  locker.release() called.(不需要对象实例)")


def deco(cls):
    """
    cls 必须实现acquire和release静态方法
    """

    def _deco(func):
        def __deco():
            print("before %s called [%s]." % (func.__name__, cls))
            cls.acquire()
            try:
                return func()
            finally:
                cls.release()

        return __deco

    return _deco


@deco(Locker)
def myfunc():
    print(" myfunc() called.")
myfunc()

functool.wraps

如果把注释那行去掉会得到完全不同的结果,原因是一个函数被装饰后自身的元信息会被覆盖掉,@wraps(fun)就是用来避免这种情况的。

from functools import wraps


def decorator(fun):
    # @wraps(fun)
    def _decorator(*args, **kwargs):
        """
        This is _decorator()
        :param args:
        :param kwargs:
        :return:
        """
        return fun(*args, **kwargs)
    return _decorator

@decorator
def cube(a):
    """
    This is fun()
    :param a:
    :return:
    """
    print(a**3)

print("cube.__name__:\n\n\t\t" + cube.__name__)
print()
print("cube.__doc__:\n" + str(cube.__doc__))

类装饰器

使用类装饰器可以依靠类内部的__call__方法,当使用@形式将装饰器附到函数上时,就会调用此方法。

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

    def __call__(self):
        print('class decorator runing')
        self._func()
        print('class decorator ending')


@Foo
def bar():
    print('bar')

bar()

类装饰器的更多应用

Python内置装饰器

@staticmathod、@classmethod、@property

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值