python怎么用类装饰器,python用类作为装饰器

python的decorator是python比较有名的语法糖之一,一般的模式是把一个需要加装饰器的 方法传入一个装饰器方法,然后系统调用的时候其实是调用的装饰之后的方法,这种方法 的好处就是有的时候我们可能需要加一些即时,或者加一些统计项的时候,可以不和业务

python的decorator是python比较有名的语法糖之一,一般的模式是把一个需要加装饰器的 方法传入一个装饰器方法,然后系统调用的时候其实是调用的装饰之后的方法,这种方法 的好处就是有的时候我们可能需要加一些即时,或者加一些统计项的时候,可以不和业务 逻辑代码混在一起。举一个非常简单的例子,就是执行一些cgi的方法的时候大都需要判断 登录,所以我们代码里面可能有这么一段

def login_required(fn):

def dec_func(*args,**keyargs):

if notlogin():

return json.dumps({"code":CODE_NOT_LOGIN})

else:

return fn(*args,**keyargs)

@app.get("/path/of/this/func")

@login_required

def cgifn(t):

return json.dumps({"code":CODE_SUCCESS})

今天看falsk源代码的时候发现还有另外一种用法,大概代码如下(为了简便,只摘抄了部分) 从下面我们可以看出,在name上面的装饰漆是一个类

class Flask():

@locked_cached_property

def name(self):

"""The name of the application. This is usually the import name

with the difference that it's guessed from the run file if the

import name is main. This name is used as a display name when

Flask needs the name of the application. It can be set and overridden

to change the value.

.. versionadded:: 0.8

"""

if self.import_name == '__main__':

fn = getattr(sys.modules['__main__'], '__file__', None)

if fn is None:

return '__main__'

return os.path.splitext(os.path.basename(fn))[0]

return self.import_name

class locked_cached_property(object):

"""A decorator that converts a function into a lazy property. The

function wrapped is called the first time to retrieve the result

and then that calculated result is used the next time you access

the value. Works like the one in Werkzeug but has a lock for

thread safety.

"""

def __init__(self, func, name=None, doc=None):

self.__name__ = name or func.__name__

self.__module__ = func.__module__

self.__doc__ = doc or func.__doc__

self.func = func

self.lock = RLock()

def __get__(self, obj, type=None):

if obj is None:

return self

with self.lock:

value = obj.__dict__.get(self.__name__, _missing)

if value is _missing:

value = self.func(obj)

obj.__dict__[self.__name__] = value

return value

这种使用方式和一般的使用方式还是有很大差别的,所以让我觉得有点好奇,好奇的点有几 个地方,第一个是既然是装饰器,那上面的locked_cached_property装饰的时候调用了什 么,第二个是装饰之后如何使用。

首先谈谈装饰,装饰器应该是对python编译器在编译被装饰的对象的时候,以被装饰方法为 参数,传入装饰器方法,然后返回一个新的方法绑定到被装饰的方法的名字上面。那这里如 果是一个类的话,那就会调用类的初始化方法,生成一个此类的实例绑定到了名字上面。就 像如下的代码一样,我们的abc应该就变成了一个cached_property的一个实例。这样如果 我们访问A类一个对象的abc的时候,python在对某个实例调用属性的时候,会先看属性指向 的对象是否有get方法,如果有的话,那么就会尝试返回这个属性指向对象的get方 法返回的值,所以下面使用a的abc的时候,是通过直接使用属性的方式,而不是方法调用的 方式,这应该得益于python里面所有都是对象的好处。

#encoding=utf8

_missing = None

class cached_property(object):

def __init__(self, func, name=None, doc=None):

self.__name__ = name or func.__name__

self.__module__ = func.__module__

self.__doc__ = doc or func.__doc__

self.func = func

def __get__(self, obj, type=None):

if obj is None:

return self

value = obj.__dict__.get(self.__name__, _missing)

if value is _missing:

value = self.func(obj)

obj.__dict__[self.__name__] = value

return value

class A():

@cached_property

def abc(self):

return 'yes'

b = A()

print b.abc

print b.abc()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值