2013-08-17 2 views
0

사용자 정의 사용자 모델을 참조하여 일부 처리를 수행해야하는 장고 모델이 하나 있습니다.게으른 클래스 속성 데코레이터

클래스 로딩 시간에 클래스의로드 순서를 알 수 없으므로이 모델의 클래스로 작업 할 수 없습니다.

def __new__(cls, *args, **kwargs): 
    # hack to avoid INSTALLED_APPS initialization conflicts. 
    # get_user_model() can't be called from this module at class loading time, 
    # so some class attributes must be added later. 
    # Metaclasses could me more appropiate but I don't want to override 
    # dango's metaclasses. 
    if not hasattr(cls, '_reverse_field_name_to_user'): 
     cls._find_reverse_field_name_to_user() 
    return Group.__new__(cls, *args, **kwargs) 

그것은 작동하지만 내가 뭔가를 사용하는 방법에 대한 생각했습니다 끔찍한 같습니다

그래서 나는 어떤 클래스는 내가 같은 __init__ 또는 __new__에서 그들을 추가 해요 순간에, 런타임에 속성을 추가 할 필요가 이 속성들에 대해 @lazyclassproperty을 좋아하십시오.

나는 @classproperty@lazyproperty 데코레이터를 발견했지만 둘 모두에 대해서는 그렇지 않습니다. 어떻게 작성하나요?

질문 : 어떻게 그러한 장식자를 코딩 할 수 있습니까? 또는 현재의 바보 같은 구현에 대한 또 다른 청결한 대안을 제안하십시오.

답변

3

피라미드 프레임 워크는 reify라는 아주 좋은 장식을 가지고 있지만 그것은 단지 인스턴스 수준에서 작동, 당신은 클래스 레벨을 원하는, 그래서 그것을 조금

class class_reify(object): 
    def __init__(self, wrapped): 
     self.wrapped = wrapped 
     try: 
      self.__doc__ = wrapped.__doc__ 
     except: # pragma: no cover 
      pass 

    # original sets the attributes on the instance 
    # def __get__(self, inst, objtype=None): 
    # if inst is None: 
    #  return self 
    # val = self.wrapped(inst) 
    # setattr(inst, self.wrapped.__name__, val) 
    # return val 

    # ignore the instance, and just set them on the class 
    # if called on a class, inst is None and objtype is the class 
    # if called on an instance, inst is the instance, and objtype 
    # the class 
    def __get__(self, inst, objtype=None): 
     # ask the value from the wrapped object, giving it 
     # our class 
     val = self.wrapped(objtype) 

     # and set the attribute directly to the class, thereby 
     # avoiding the descriptor to be called multiple times 
     setattr(objtype, self.wrapped.__name__, val) 

     # and return the calculated value 
     return val 

class Test(object): 
    @class_reify 
    def foo(cls): 
     print "foo called for class", cls 
     return 42 

print Test.foo 
print Test.foo 

실행 프로그램을 수정할 수 있으며

를 인쇄
foo called for class <class '__main__.Test'> 
42 
42 
+0

매력처럼 작동합니다. 많은 감사, 나는 한 번 이상 upvote 수 있었으면 좋겠다! –

관련 문제