2017-04-24 12 views
3

목표는 애트리뷰트의 lazyloading을 허용하는 커스텀 파이썬 클래스를 만드는 것이다. 게으른 액세스. 여기 예제 :이 예에서퍼스트 클래스 애트리뷰트 액세스시 파이썬 커스텀 초기화

class LazyDateModule() 
    def __init__(self, args): 
     self.args = args 
     self._expensive_date_attr = None 

    def _expensive_init(): 
     time.sleep(10) 
     self._expensive_date_attr = date.today() 

    @memoize 
    def date_str(): 
     return str(self._expensive_date_attr) 

    @memoize 
    def month_num(): 
     return self._expensive_date_attr.month 

, 내 @memoize 장식 나를 위해 캐싱 단계를 처리합니다.

나는 다른 곳에서 내 LazyDateModule를 정의하고있어 경우

LDM = LazyDateModule() 

어떻게 만 memoized 속성 방법 중 하나에 액세스 한 처음에 _expensive_init()를 실행합니까? 나는 이와 같은 것을 시도했다 :

class LazyDateModule() 
    def __init__(self, args): 
     self.args = args 
     self._assembled = False 
     self._expensive_date_attr = None 

    def _expensive_init(): 
     time.sleep(10) 
     self._expensive_date_attr = date.today() 
     self._assembled = True 

    @memoize 
    def date_str(): 
     if self._assembled is False: 
      self._expensive_init() 
     return str(self._expensive_date_attr) 

    @memoize 
    def month_num(): 
     if self._assembled is False: 
      self._expensive_init() 
     return self._expensive_date_attr.month 

그러나 그것은 매우 깨끗하지 않다. 이상적으로는이 동작을 클래스 수준에서 사용하길 원하지만, __getattr__ 또는 __getattribute__을 덮어 쓰려는 시도에서 고생했습니다. 다른 데코레이터도 사용할 수 있습니다.

위의 내용이 혼란 스럽다면 죄송합니다. 내가 그것을 어떤 방식 으로든 분명히 할 수 있다면 알려줘!

편집 1 : 위의 예는 너무 간단하다고 생각합니다. 내 _expensive_init()가 단일 속성을 정의하는 것과는 대조적으로 많은 작업을 수행한다고 가정 해 보겠습니다.

def _expensive_init(self): 
    time.sleep(5) 
    self._expensive_date_attr = date.today() 

    time.sleep(1) 
    # send a message to someone saying that this occurred 

    time.sleep(1) 
    # run a db call to update when this action occurred 

    etc... 

이 메서드는 다양한 동작을 처리하는 것이 가장 이상적입니다.

+0

나는 비슷한 모듈을 썼다. 나는 그것을 끝내지 않기로 결정했다. 그것은 두 단계로 진행되었습니다. 첫 번째 단계에서 간단한 메소드 데코레이터는 데코 레이팅 된 함수 자체에 속성을 추가하여 메모 할 모든 메소드를 등록합니다. 그 당시에는 클래스 자체가 존재하지 않기 때문에 이것이 모두 가능합니다. 두 번째 단계에서 클래스 데코레이터는 추가 된 속성에 대한 모든 메소드를 검사하고, 테이블을 만들고, 클래스에서 해당 메소드를 제거하고, 테이블의 이름에 대한 첫 번째 액세스를 포착하고 함수를 호출하고 결과를 일반 속성으로 표시합니다. 희망이 도움이됩니다. – VPfB

답변

2

캐싱 데코레이터 memoize이 있으니 _expensive_date_attr을 캐시하는 것이 어떨까요? 그리고 BTW는 그것을 재산으로 바꾼다 :

class LazyDateModule(): 
    def __init__(self, args): 
     self.args = args 
     self._assembled = False 

    @memoize 
    @property 
    def _expensive_date_attr(self): 
     return date.today 

    @memoize 
    def date_str(): 
     return str(self._expensive_date_attr) 

    @memoize 
    def month_num(): 
     return self._expensive_date_attr.month 
+0

'date_str'과'month_num'도 메모해야하는 이유가 있습니까? – VPfB

+0

코드에 암기되어있는 것 외의 다른 이유가 없습니다. – Guillaume

+0

이것은 깨끗합니다.하지만 불행히도 저는 이것이 제가 구상중인 것에 대해서는 효과가 없을 것이라고 생각하지 않습니다. 이 점에서보기는 너무 간단합니다. 최근 변경 사항을 확인하십시오. – dizzyf