python修饰器原理_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的修饰器如何应用 应该都明白 了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值