2013-03-07 2 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

+1

Ваш последний выглядит хорошо. 'hasattr' в порядке. – katrielalex

+0

ваш код в порядке. Я бы пропустил hasattr и попытался поймать AttributeError вместо этого, то есть более путинский. «Проще просить прощения, чем разрешение» http://stackoverflow.com/questions/6092992/why-is-it-easier-to-ask-forgiveness-than-permission-in-python-but-not-in-java – theAlse

ответ

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 
Смежные вопросы