OLD | NEW |
(Empty) | |
| 1 # Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. |
| 4 |
| 5 import functools |
| 6 |
| 7 |
| 8 class cached_property(object): |
| 9 """Like @property, except that the result of get is cached on |
| 10 self.{'_' + fn.__name__}. |
| 11 |
| 12 NOTE: This implementation is not threadsafe. |
| 13 |
| 14 >>> class Test(object): |
| 15 ... @cached_property |
| 16 ... def foo(self): |
| 17 ... print "hello" |
| 18 ... return 10 |
| 19 ... |
| 20 >>> t = Test() |
| 21 >>> t.foo |
| 22 hello |
| 23 10 |
| 24 >>> t.foo |
| 25 10 |
| 26 >>> t.foo = 20 |
| 27 >>> t.foo |
| 28 20 |
| 29 >>> del t.foo |
| 30 >>> t.foo |
| 31 hello |
| 32 10 |
| 33 >>> |
| 34 """ |
| 35 def __init__(self, fn): |
| 36 self.func = fn |
| 37 self._iname = "_" + fn.__name__ |
| 38 functools.update_wrapper(self, fn) |
| 39 |
| 40 def __get__(self, inst, cls=None): |
| 41 if inst is None: |
| 42 return self |
| 43 if not hasattr(inst, self._iname): |
| 44 val = self.func(inst) |
| 45 # Some methods call out to another layer to calculate the value. This |
| 46 # higher layer will assign directly to the property, so we have to do |
| 47 # the extra hasattr here to determine if the value has been set as a side |
| 48 # effect of func() |
| 49 if not hasattr(inst, self._iname): |
| 50 setattr(inst, self._iname, val) |
| 51 return getattr(inst, self._iname) |
| 52 |
| 53 def __delete__(self, inst): |
| 54 assert inst is not None |
| 55 if hasattr(inst, self._iname): |
| 56 delattr(inst, self._iname) |
OLD | NEW |