为了账号安全,请及时绑定邮箱和手机立即绑定

Python备忘录/延迟查找属性装饰器

Python备忘录/延迟查找属性装饰器

繁星coding 2019-10-24 11:07:57
最近,我浏览了现有的代码库,其中包含许多类,其中实例属性反映了存储在数据库中的值。我已经重构了许多这些属性,以便推迟它们的数据库查找。不会在构造函数中初始化,而只能在初读时进行初始化。这些属性不会在实例的整个生命周期内发生变化,但是它们是第一次计算的真正瓶颈,只有在特殊情况下才真正访问。因此,它们也可以在从数据库中检索出来之后进行缓存(因此,它适合于记忆的定义,其中输入只是“无输入”)。我发现自己一遍又一遍地为各种类的各种属性键入以下代码片段:class testA(object):  def __init__(self):    self._a = None    self._b = None  @property  def a(self):    if self._a is None:      # Calculate the attribute now      self._a = 7    return self._a  @property  def b(self):    #etc我已经不知道有没有使用Python的现有装饰器来执行此操作?或者,是否有合理简单的方法来定义装饰器,从而做到这一点?我正在Python 2.5下工作,但是2.6答案如果有很大不同,可能仍然很有趣。注意在Python包含许多现成的装饰器之前,就曾问过这个问题。我更新它只是为了更正术语。
查看完整描述

3 回答

?
婷婷同学_

TA贡献1844条经验 获得超8个赞

对于各种强大的工具,我都使用bolton。


作为该库的一部分,您具有cached属性:


from boltons.cacheutils import cachedproperty


class Foo(object):

    def __init__(self):

        self.value = 4


    @cachedproperty

    def cached_prop(self):

        self.value += 1

        return self.value



f = Foo()

print(f.value)  # initial value

print(f.cached_prop)  # cached property is calculated

f.value = 1

print(f.cached_prop)  # same value for the cached property - it isn't calculated again

print(f.value)  # the backing value is different (it's essentially unrelated value)


查看完整回答
反对 回复 2019-10-24
?
凤凰求蛊

TA贡献1825条经验 获得超4个赞

这是惰性属性装饰器的示例实现:


import functools


def lazyprop(fn):

    attr_name = '_lazy_' + fn.__name__


    @property

    @functools.wraps(fn)

    def _lazyprop(self):

        if not hasattr(self, attr_name):

            setattr(self, attr_name, fn(self))

        return getattr(self, attr_name)


    return _lazyprop



class Test(object):


    @lazyprop

    def a(self):

        print 'generating "a"'

        return range(5)

互动环节:


>>> t = Test()

>>> t.__dict__

{}

>>> t.a

generating "a"

[0, 1, 2, 3, 4]

>>> t.__dict__

{'_lazy_a': [0, 1, 2, 3, 4]}

>>> t.a

[0, 1, 2, 3, 4]


查看完整回答
反对 回复 2019-10-24
?
慕工程0101907

TA贡献1887条经验 获得超5个赞

我为自己编写了此代码...用于真正的一次性计算的惰性属性。我喜欢它,因为它避免在对象上粘贴额外的属性,并且一旦激活就不会浪费时间检查属性是否存在,等等:


import functools


class lazy_property(object):

    '''

    meant to be used for lazy evaluation of an object attribute.

    property should represent non-mutable data, as it replaces itself.

    '''


    def __init__(self, fget):

        self.fget = fget


        # copy the getter function's docstring and other attributes

        functools.update_wrapper(self, fget)


    def __get__(self, obj, cls):

        if obj is None:

            return self


        value = self.fget(obj)

        setattr(obj, self.fget.__name__, value)

        return value



class Test(object):


    @lazy_property

    def results(self):

        calcs = 1  # Do a lot of calculation here

        return calcs

注意:lazy_property该类是一个非数据描述符,这意味着它是只读的。添加__set__方法会阻止其正常工作。


查看完整回答
反对 回复 2019-10-24
  • 3 回答
  • 0 关注
  • 420 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信