python 修饰器 应用场景

久久不用,发现又忘了修饰器是怎么用的了。记在博客里会妥妥点。

一、 什么是修饰器:

1、以我的理解来说,修饰器就是为了给被修饰的函数进行预处理。什么是预处理呢?

比如说下面这个例子:

def myDeco(func):
    print("Hello ,I'm Decorator!")
    return func

@myDeco
def run():
    print("func:run")

run()
输出结果 :
ubuntu@yee:/tmp$ python test.py 
Hello ,I'm Decorator!
func:run
可以看到,在执行run之前,先经过了myDeco来进行一些预处理。具体在现实中是如何运用的,下文再说。

2、处理参数 

def myDeco(func):
    print("Hello ,I'm Decorator!")
    def _myDeco(*args,**kwargs): //被修饰的函数的参数 
        print("my name:%s",func.__name__)
        ret = func(*args,**kwargs)
        return ret
    return _myDeco

@myDeco
def run(a,b):
    print("func run start:")
    print("---------------")
    print("run(%s,%s)" % (a,b))
    print("---------------")
    print("func run end")


run(1,2)

3、带参数的修饰器:

def myDeco(args):
    print("Hello ,I'm Decorator!")
    print("args:",args) //处理参数 
    def _myDeco(func)://处理函数 
        def __myDeco(*args,**kwargs): //处理函数的参数 
            print("my name:%s",func.__name__)
            ret = func(*args,**kwargs)
            return ret
        return __myDeco
    return _myDeco

@myDeco("my_name")
def run(a,b):
    print("func run start:")
    print("---------------")
    print("run(%s,%s)" % (a,b))
    print("---------------")
    print("func run end")


run(1,2)

其它的还有“带类参数的修饰器”等一些高级特性,不过我没用过,就不记了。

二、具体应用 :

了解一些语法功能之后,总是需要知道它的应用场景吧,不然就没有用处了。

我以 tornado 这个web框架为例来说一下它的具体使用场景 。

先看代码就明白了:

class MessageNewHandler(BaseHandler,MessageMixin)://聊天室中的新消息处理,接收新消息
    @tornado.web.authenticated                    //必须经过登录认证
    def post(self):
        user  = self.get_current_user()
        message = {
                "id":str(uuid.uuid4()),
                "current_user":user.id,
                'up':0,
        }
上面的代码已经很明确了,在聊天室中的用户 post一条新消息之前,tornado会先检查用户是否已经登录认证了,只有经过认证的用户才可以post消息。

看看tornado.web.authenticated 是怎么实现的:

def authenticated(method):
    """Decorate methods with this to require that the user be logged in."""
    @functools.wraps(method)
    def wrapper(self, *args, **kwargs):
        if not self.current_user:
            if self.request.method in ("GET", "HEAD"):
                url = self.get_login_url()
                if "?" not in url:
                    if urlparse.urlsplit(url).scheme:
                        # if login url is absolute, make next absolute too
                        next_url = self.request.full_url()
                    else:
                        next_url = self.request.uri
                    url += "?" + urllib.urlencode(dict(next=next_url))
                self.redirect(url)
                return
            raise HTTPError(403)
        return method(self, *args, **kwargs)
    return wrapper

---------------------------------------------------------------

简单讲一下 functools.wraps 这个修饰器的作用:

functools 这个工具提供了三个函数:partial ,update_wrapper,wraps ,而wraps 只是对 update_wrapper进行了封装一下而已。

在修饰器

def myDeco(func)

    return func

这一句中,func 实际上已经丢掉了原func 的几个属性:__name__、__module__、__doc__和 __dict__,所以,返回后的函数你无法再使用  func.__doc__  来获得注释内容 ,而如果改成这样:

def myDeco(func):

    @functools.wraps(func)

    def _myDeco(*args,**kwargs):

        return func(*args,**kwargs)

    return _myDeco

则 functools.wraps 会帮你重新绑定在返回的新函数上。

---------------------------------------------------------------

说回到tornado 的例子,看它是怎么做认证 预处理的。

首先是:

if not self.current_user

判断是否当前用户(self.current_user是tornado的内置变量,保存当前登录的用户),如果不是,则抛出错误:

raise HTTPError(403)
否则就返回 :
return method(self, *args, **kwargs)
表示认证成功,开发者可以继续对认证成功的用户做应该做的动作。

这样子,python的修饰器如何应用 应该都明白 了。


转载于:https://my.oschina.net/jbryan/blog/135552

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值