最近在看blinker模块源码。blinker模块是一个消息传递模块,flask里面用到的信号机制就是源自于blinker。
有很多函数打上了@lazy_property,不解。查看源码:
class lazy_property(object):
"""A @property that is only evaluated once."""
def __init__(self, deferred):
self._deferred = deferred # 延期的,就是func
self.__doc__ = deferred.__doc__
def __get__(self, obj, cls):
if obj is None:
return self
value = self._deferred(obj)
setattr(obj, self._deferred.__name__, value)
return value
发现这是一个类装饰器,通过搜索,发现这个装饰器的作用和@property类似,不同的是,@property每次调用的时候都会对属性进行重复运算,造成了额外开销,但是@lazy_property只在第一次调用的时候进行计算,随即调用setattr(obj,name,val)把这个值保存到自己的属性里。
另外一层含义就是这个属性不是随着对象的创建而创建,而是在调用的时候才创建,所以叫做lazy property。
这是网上的一个例子:
class lazy(object):
def __init__(self, func):
self.func = func
def __get__(self, instance, cls):
val = self.func(instance) # 其相当于执行的area(c),c为下面的Circle对象
setattr(instance, self.func.__name__, val)
return val
class Circle(object):
def __init__(self, radius):
self.radius = radius
@lazy
def area(self):
print('evalute')
return 3.14 * self.radius ** 2
c = Circle(4)
print(c.area)
print(c.area)
print(c.area) # 三j次的结果都是:50.24
只有第一次打印evalute
之后只打印50.24