Python 装饰器(decorator)总结

最近总体研究了一下python的装饰器,在这里做一下总结

普通装饰器

普通装饰器基本如下,使用起来简单方便,下面这个是最简单的例子,调用方法前打印一下方法的名字

def decorator(func):
    def wrapper():
        print func.__name__
        func()
    return wrapper

@decorator
def func():
    do something

稍微解释一下,func这个函数在被编译器编译之后会变成这样,因此调用的时候实际上是掉用的wrapper这个函数了

func = decorator(func)

带参数函数的装饰器

上面提到的普通装饰器,装饰的是没有参数的函数,下面这个展示的是如果写一个带有参数的函数的装饰器,其实也很简单

def decorator(func):
    def wrapper(*args, **kwargs):
        print func.__name__
        func(*args, **kwars)
    return wrapper

@decorator
def func(something):
	print something

装饰器本身带参数

装饰器本身带参数个人认为是很常见的用法,可以对装饰器本身做一些控制,从代码看跟无参数装饰器最直观的区别就是要多包一层

def decorator(arg):
    def wrapper(func):
        def inner_wrapper(*args, **kwargs):
            print args
            print func.__name__
            func(*args, **kwargs)
        return inner_wrapper
    return wrapper

@decorator(arg=arg)
def func(something):
	print something

类作为装饰器

类作为装饰器这个平时用的不多,这个用法还是很神奇的,主要是要用到__call__方法

class Decorator(object):  # python3 中就不需要显式的继承object了
    def __init__(self, func):
        self.func = func
	
    def __call__(self, *args, **kwargs):
        print self.func.__name__
        func(*args, **kwargs)

@Decorator
def func(something):
	print something

跟普通装饰器其实是一样的,调用Decorator装饰的方法func相当于是 

Decorator(func).__call__()

类作为带参数的装饰器

有了上面这几个装饰器做基础,这个理解起来也不难

class Decorator(object):
    def __init__(self, arg):
        self.arg = arg
	
    def __call__(self, func):
        def wrapper(*args, **kwargs):
            print func.__name__
            func(*args, **kwargs)
        return wrapper

@Decorator(arg=arg)
def func(something):
print something

使用装饰器的一些坑

1. 错误的函数签名和文档

    装饰器装饰过的函数看上去名字没变,其实已经变了,包括doc。使用标准库里的functools.warps基本可以解决这个问题

def decorator(func):
    @warps(func)
    def warpper(*args, **kwargs):
        return func(*args, **kwargs)
    return wrapper

 2. 不能用来装饰@classmethod 和 @staticmethod

    因为@staticmethon和@classmethod返回的并不是一个callable对象,而是一个staticmethod的对象,这不符合装饰器的定义。解决方案是把装饰器放在@classmethod和@staticmethod之前。注意这里说的之前不是写在前一行,而是后一行,因为装饰器是从离函数最近的这个开始起作用的

@classmethod
@decorator
def func():
    do_something

    

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值