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

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

répondre à tous(2)
洪涛

Selon la méthode d'implémentation de memoized_property, les réponses suivantes ont toutes une prémisse, c'est-à-dire qu'il est supposé qu'elle est utilisée comme décorateur pour les fonctions de classe. À ce stade, cette classe peut être considérée comme une version modifiée du décorateur de propriétés. L'effet de mise en cache peut être obtenu car Python a la priorité lors de l'accès aux attributs .

Pour a.val, Python effectue le traitement suivant :

  1. accède d'abord au __dict__ de l'objet, c'est-à-dire a.__dict__['val'] ;

  2. S'il n'y a pas de
  3. pour accéder à nouveau à la classe, elle recherchera vers le haut le long de la relation d'héritage

    A.__dict__['val'] ;

  4. Si
  5. est trouvé et qu'une valeur est renvoyée, alors la valeur est obtenue ; si un descripteur est renvoyé, la méthode

    du descripteur sera appelée A.__dict__['val']__get__ ;

  6. Pour
ici :

memoized_propertyPar exemple, cette classe encapsule la fonction val de la classe A :

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

a = A()
a.val

Lors du premier accès à

, selon la séquence de recherche ci-dessus : il n'est pas trouvé dans l'objet, passez à la deuxième étape, il est trouvé dans le dictionnaire de classe, mais il s'agit d'un descripteur ; , il entrera donc le descripteur dans la méthode

. Ici, après avoir utilisé val pour appeler la fonction décorée __get__ et calculer le résultat, tout en renvoyant le résultat, le résultat est également stocké dans self.fget(obj). La prochaine fois que vous visiterez val, puisque le obj.__dict__['val'] de l'objet contient a.val, il recherchera __dict__ d'abord au lieu de tout mettre en œuvre pour trouver val. Cela permet d'obtenir l'effet de mettre en cache un attribut. Le général obj.__dict__['val'] ne réglera pas __get__, il sera donc recalculé à chaque fois. __get__ obj.__dict__['xxx']Après avoir compris cela,

c'est très clair, il suffit de supprimer le chemin avec la priorité précédente. Ensuite, Python a dû rechercher étape par étape la priorité et a découvert que

était disponible, il a donc appelé la méthode reset et l'a recalculée à nouveau. __get__ a.valEt l'intérieur de

peut être considéré comme bien meilleur. . . .

Ty80

Une méthode de classe est une méthode que vous pouvez appeler directement sans instancier la classe

Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal