Python, 理解下面这个装饰器(based on class), 有哪几个关键点 ?
怪我咯
怪我咯 2017-04-18 10:33:42
0
2
496
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)
怪我咯
怪我咯

走同样的路,发现不同的人生

reply all(2)
洪涛

According to the implementation method of memoized_property, the following answers all have a premise, that is, it is assumed that it is used as a decorator for class functions. At this time, this class can be regarded as a modified version of the property decorator. The caching effect can be achieved because Python has priority when accessing attributes.

For a.val, Python performs the following processing:

  1. Access the object’s __dict__,即a.__dict__['val'] first;

  2. If there is no access to the class again, A.__dict__['val'] will be searched along the inheritance relationship;

  3. If A.__dict__['val'],返回的是值的话,那么就获得该值;如果返回的是一个描述器,则会调用描述器的__get__ is found and a value is returned, then the value will be obtained; if a descriptor is returned, the

    method of the descriptor will be called;

memoized_propertyFor the

here:

For example, this class encapsulates the val function of class A:

class A(object):
    ...
    
    @memoized_property
    def val(self):
        ...

a = A()
a.val
val的时候,根据上面的查找顺序:对象里面没有,跳到第二步;在类的字典里发现了,但发现是描述器,因此会进入到描述器中的__get__方法中。在这里,使用self.fget(obj)调用装饰的val函数并计算结果后,在返回结果的同时,将结果也存储在obj.__dict__['val']中。下次再访问a.val的时候,由于对象的__dict__中有val了,就会先查找obj.__dict__['val'],而不会大动干戈的去找__get__。这样就实现缓存一个属性的效果。而一般的__get__是不会设置obj.__dict__['xxx']When accessing val for the first time, according to the above search sequence: it is not in the object, jump to the second step; it is found in the class dictionary, but it is found to be a descriptor, so it will be entered to the method in the descriptor. Here, use self.fget(obj) to call the decorated val function and calculate the result. While returning the result, the result is also stored in obj. __dict__['val']. The next time you visit

, since there is val in the object's __dict__, it will first search for obj.__dict__['val'] , and will not go to great lengths to find itreset就很清楚了,只不过把上一个优先级的途径去掉。然后Python就不得不沿着优先级一步步找下去,发现__get__可用,于是又在其中调用a.val. This achieves the effect of caching an attribute. Generally, obj.__dict__['xxx'] is not set, so it is recalculated every time.

After understanding this, reset is very clear, it just removes the previous priority path. Then Python had to search step by step along the priority and found that __get__ was available, so it called the

method in it and recalculated it again. 🎜 🎜And the interior of 🎜 can be said to be much better. . . . 🎜
Ty80

A class method is a method that you can call directly without instantiating the class

Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template