Python, 理解下面这个装饰器(based on class), 有哪几个关键点 ?
澳门银河官网
澳门银河官网
当前位置 : 澳门银河官网 > 澳门银河官网

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

class memoized_propertyobject:
    """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.fgetobj
        return result

    def _resetself, obj:
        memoized_property.resetobj, self.__name__

    @classmethod
    def resetcls, obj, name:
        obj.__dict__.popname, None

根据memoized_property的实现方法,下面的答案都有一个前提,即假设其作为对类函数的装饰器来使用。此时这个类可以看作是property装饰器的修改版。能够实现缓存的效果是因为Python访问属性时是有优先级的

对于a.val,Python进行如下处理:

  1. 先访问对象的__dict__,即a.__dict__[val]

  2. 如果没有再访问类的A.__dict__[val],此时会沿着继承关系一直向上寻找;

  3. 如果找到A.__dict__[val],返回的是值的话,那么就获得该值;如果返回的是一个描述器,则会调用描述器的__get__方法;

对于这里的memoized_property来说:

比如这个类封装了A类的val函数:

class Aobject:
    ...
    
    @memoized_property
    def valself:
        ...

a = A
a.val

在第一次访问val的时候,根据上面的查找顺序:对象里面没有,跳到第二步;在类的字典里发现了,但发现是描述器,因此会进入到描述器中的__get__方法中。在这里,使用self.fgetobj调用装饰的val函数并计算结果后,在返回结果的同时,将结果也存储在obj.__dict__[val]中。下次再访问a.val的时候,由于对象的__dict__中有val了,就会先查找obj.__dict__[val],而不会大动干戈的去找__get__。这样就实现缓存一个属性的效果。而一般的__get__是不会设置obj.__dict__[xxx]的,所以每次都是重新计算。

明白了这些以后,reset就很清楚了,只不过把上一个优先级的途径去掉。然后Python就不得不沿着优先级一步步找下去,发现__get__可用,于是又在其中调用a.val方法重新计算了一遍。

__get__的内部,又能说好多了。。。。

类方法就是当你不用做类的实例化就可以直接调用的方法

栏目列表

广告位

澳门银河官网