-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmemoized_property.py
More file actions
69 lines (56 loc) · 2.37 KB
/
memoized_property.py
File metadata and controls
69 lines (56 loc) · 2.37 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# -*- coding: utf-8 -*-
"""
property デコレータの代わりに使う。
関数の実行を1度だけ行い、計算結果をインスタンス変数として格納しておく。
再度呼び出しが行われた場合、関数をコールせず、インスタンス変数から結果を返す。
slots が定義されているとうまくいかないかもしれない。
class Hoge(object):
@memoized_property
def calc(self):
some cord....
一応、セッターなんかも設定できるようにしたが未テスト
セッター、デリーターのコールでキャッシングしてるクラス変数を削除するので、
その後にゲッターがコールされると再計算を行う…はず。
"""
class memoized_property(object):
def __init__(self, fget=None, fset=None, fdel=None, doc=None):
if doc is None and fget is not None and hasattr(fget, "__doc__"):
doc = fget.__doc__
self.__get = fget
self.__set = fset
self.__del = fdel
self.__doc__ = doc
if fget is not None:
self._attr_name = '___'+fget.func_name
def __get__(self, inst, type=None):
if inst is None:
return self
if self.__get is None:
raise AttributeError, "unreadable attribute"
if not hasattr(inst, self._attr_name):
result = self.__get(inst)
setattr(inst, self._attr_name, result)
return getattr(inst, self._attr_name)
def __set__(self, inst, value):
if self.__set is None:
raise AttributeError, "can't set attribute"
delattr(inst, self._attr_name)
return self.__set(inst, value)
def __delete__(self, inst):
if self.__del is None:
raise AttributeError, "can't delete attribute"
delattr(inst, self._attr_name)
return self.__del(inst)
def memoized_property_set(inst, func_name, value):
"""
memoized_property用の属性に値をセット。
次に memoized_property デコレータがついたプロパティから値を読み出す時、
ここで保存している値が使われる
"""
if isinstance(func_name, basestring):
property_name = '___' + func_name
elif hasattr(func_name, 'func_name'):
property_name = '___' + func_name.func_name
else:
raise
setattr(inst, property_name, value)