>  Q&A  >  본문

Python, 理解下面这个装饰器(based on class), 有哪几个关键点 ?

class memoized_property(object):
    """A read-only @property that is only evaluated once."""

    def __init__(self, fget, doc=None):
        self.fget = fget
        self.__doc__ = doc or fget.__doc__
        self.__name__ = fget.__name__

    # 这个方法应该是这个缓存装饰器的关键
    # 因此, 我组织关键字如下
    #     * python __get__
    #     * how python __get__ works
    #     # python descript tools
    def __get__(self, obj, cls):
        if obj is None:
            return self
        obj.__dict__[self.__name__] = result = self.fget(obj)
        return result

    def _reset(self, obj):
        memoized_property.reset(obj, self.__name__)

    @classmethod
    def reset(cls, obj, name):
        obj.__dict__.pop(name, None)
怪我咯怪我咯2741일 전467

모든 응답(2)나는 대답할 것이다

  • PHP中文网

    PHP中文网2017-04-18 10:35:42

    memoized_property의 구현 방법에 따르면 다음 답변은 모두 전제가 있습니다. 즉, 클래스 함수의 데코레이터로 사용된다고 가정합니다. 이때 이 클래스는 속성 데코레이터의 변형 버전이라고 볼 수 있다. 파이썬이 속성에 접근할 때 우선순위를 가지기 때문에 캐싱 효과를 얻을 수 있습니다.

    a.val의 경우 Python은 다음 처리를 수행합니다.

    1. 은 먼저 개체의 __dict__, 즉 a.__dict__['val']

      에 액세스합니다.
    2. 클래스에 다시 액세스할

      이 없으면 상속 관계를 따라 위쪽으로 검색합니다. A.__dict__['val']

    3. 이 발견되고 값이 반환되면 설명자가 반환되면 설명자의
    4. 메서드가 호출됩니다.

      A.__dict__['val']__get__의 경우:

    5. 예를 들어, 이 클래스는 클래스 A의 val 함수를 캡슐화합니다.
    으아악

    처음으로 memoized_property에 접근할 때 위의 검색 순서에 따라: 객체에서 발견되지 않고, 두 번째 단계로 점프하여 클래스 사전에서 발견되지만 디스크립터로 발견됩니다. 이므로

    메서드에 설명자를 입력합니다. 여기서

    를 이용해 데코레이팅된

    함수를 호출해 결과를 계산한 뒤, 결과를 반환하면서 결과도

    에 저장한다. 다음에 val을 방문할 때 개체의 __get__self.fget(obj)이 포함되어 있으므로 val을 찾기 위해 모든 노력을 기울이는 대신 obj.__dict__['val']을 먼저 검색합니다. 이는 속성을 캐싱하는 효과를 얻습니다. 일반 a.val에서는 __dict__을 설정하지 않으므로 매번 다시 계산됩니다. val obj.__dict__['val']이것을 이해하고 나면__get__아주 명확합니다. 이전 우선순위가 있는 경로를 제거하면 됩니다. 그런 다음 Python은 우선순위에 따라 단계별로 검색해야 했고 __get__이 사용 가능하다는 것을 알았으므로 그 안에서 obj.__dict__['xxx'] 메서드를 호출하고 다시 계산했습니다.

    그리고 reset 인테리어도 훨씬 좋아졌다고 할 수 있죠. . . . __get__

    회신하다
    0
  • PHP中文网

    PHP中文网2017-04-18 10:35:42

    클래스 메서드는 클래스를 인스턴스화하지 않고 직접 호출할 수 있는 메서드입니다

    회신하다
    0
  • 취소회신하다