2013-03-07 47 views
1

我有一個類,我需要訪問一個計算值,只能計算每個子類。 這個計算並不便宜,而且由於子類有許多實例,所以我只想爲每個子類計算一次這個值。pythonic方式計算一個值類對象只有一次

我能想到的兩個解決方案,我真的不喜歡:

無論是父類將有一個@classmethodstart()將計算值。 這強制我確定每個類的第一個實例的確切位置,所以我已經排除了這個選項。

,或者此代碼:

class A(object): 
    @classmethod 
    def _set_cls_attribute(cls): 
     if hasattr(cls, 'big_attr'): 
      return 
     cls.big_attr = heavy_func(cls.VAL) 

    def __init__(self): 
     self._set_cls_attribute() 

class B(A): 
     VAL = 'b' 

class C(A): 
     VAL = 'c' 


for _ in range(large_number): 
     b = B() 
     c = C() 

我不喜歡使用hasattr雖然... 有什麼好?

+1

元類相救? – NPE 2013-03-07 14:36:08

+1

你的後者看起來不錯。 'hasattr'確定。 – katrielalex 2013-03-07 14:37:31

+0

你的代碼很好。我會跳過hasattr並嘗試捕獲AttributeError,這是更pythonic的方式。 「容易要求寬恕比權限」http://stackoverflow.com/questions/6092992/why-is-it-easier-to-ask-forgiveness-than-permission-in-python-but-not-in-java – theAlse 2013-03-07 14:47:24

回答

1

甲元類是沿着相同的路線和你解決這個

class A_meta(type): 
    def __init__(cls, *args): 
     type.__init__(cls, *args) 
     if hasattr(cls, 'VAL'): 
      cls.big_attr = heavy_func(cls.VAL) 

class A(object): 
    __metaclass__ = A_meta 

class B(A): 
     VAL = 'b' 

class C(A): 
     VAL = 'c' 

的另一種方式的便捷方式。這具有延遲調用heavy_func的優點,直到該屬性第一次被訪問。

class A(object): 
    def __getattr__(self, attr): 
     if attr == 'big_attr': 
      self.__class__.big_attr = heavy_func(self.VAL) 
     return object.__getattribute__(self, attr) 
1

沒有元類或hasattr:

class A(object): 
    @classmethod 
    def attribute(cls): 
     v = heavy_func(cls.VAL) 
     cls.attribute = lambda k : v 
     return v