python 动态添加装饰器_python tornado中如何给每个服务器请求动态加上装饰器?

必须是元类,用来控制类的创建。

示例代码,假设登录后get_user能返回用户名,即类B的是没有登录的:

# -*- coding: utf-8 -*-

import functools

class HttpError(Exception):

pass

def logined(func):

@functools.wraps(func)

def _wrapper(self, *args, **kwargs):

if self.user:

return func(self, *args, **kwargs)

# Or, redirect.

raise HttpError(403)

return _wrapper

class MetaWrapWithLogin(type):

def __new__(cls, name, bases, attrs):

need_login = list()

if 'need_login' in attrs:

need_login.extend(list(attrs['need_login']))

for method in need_login:

if method in attrs:

attrs[method] = logined(attrs[method])

return type.__new__(cls, name, bases, attrs)

class Base(object):

@property

def user(self):

return self.get_user()

def get_user(self):

pass

def get(self):

raise HttpError(404)

def post(self):

raise HttpError(404)

class A(Base):

__metaclass__ = MetaWrapWithLogin

need_login = ['get', 'post']

def get_user(self):

return 'foo'

def get(self):

print('{0} get'.format(self.__class__.__name__))

def post(self):

print('{0} post'.format(self.__class__.__name__))

class B(Base):

__metaclass__ = MetaWrapWithLogin

need_login = ['post']

def get(self):

print('{0} get'.format(self.__class__.__name__))

def post(self):

print('{0} post'.format(self.__class__.__name__))

if __name__ == '__main__':

a = A()

a.get()

a.post()

print('\n{0}\n'.format('-' * 10))

b = B()

b.get()

b.post()

输出:

A get

A post

----------

B get

Traceback (most recent call last):

File "test.py", line 88, in

b.post()

File "test.py", line 16, in _wrapper

raise HttpError(403)

__main__.HttpError: 403

然后按照这个思路自己改造吧。

装饰器版:

# -*- coding: utf-8 -*-

import functools

def login_decorator(func):

@functools.wraps(func)

def _wrapper(self, *args, **kwargs):

if hasattr(self, 'user') and self.user:

return func(self, *args, **kwargs)

# Or, redirect.

raise HttpError(403)

return _wrapper

def add_to_methods(decorator, *methods):

def wrap_method(cls):

for method in methods:

if hasattr(cls, method):

setattr(cls, method, decorator(getattr(cls, method)))

return cls

return wrap_method

class HttpError(Exception):

pass

@add_to_methods(login_decorator, 'post')

class A(object):

def get(self):

print('{0} get'.format(self.__class__.__name__))

def post(self):

print('{1} post'.format(self.__class__.__name__))

if __name__ == '__main__':

a = A()

a.get()

a.post()

输出:

A get

Traceback (most recent call last):

File "need.py", line 42, in

a.post()

File "need.py", line 12, in _wrapper

raise HttpError(403)

__main__.HttpError: 403

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值