Maison  >  Article  >  développement back-end  >  Comment implémenter une opération retardée en python

Comment implémenter une opération retardée en python

王林
王林avant
2023-05-16 17:16:122037parcourir

Python implémente des opérations retardées

python Si vous souhaitez implémenter des opérations retardées, vous devez appliquer du temps, puis utiliser la méthode sleep de time

Par exemple, je veux écrire une opération qui s'imprime avec un délai de 1 seconde

import time
for i in range(0, 10):
    time.sleep(1)
    print(i)

Problème de chargement retardé de Python

En Python, le chargement paresseux est beaucoup utilisé. Son idée principale est de retarder l'instanciation de la classe à introduire, économisant ainsi le temps et l'espace requis pour l'initialisation.

Cette idée est également largement utilisée dans Django, comme QuerySet d'ORM et request.user dans le middleware d'authentification, etc. Ceux-ci utilisent tous l'idée de chargement différé.

Cet article analyse l'idée du chargement paresseux à travers des exemples.

L'idée de base de l'implémentation du chargement paresseux est que je crée une classe et que nous lui transmettons la classe dont nous avons besoin pour instancier. À ce moment-là, la classe deviendra une classe de chargement paresseux lors de l'application, même si j'instancie cela. Chargement paresseux des classes, mais la classe que nous voulons référencer n'est pas instanciée.

Comme ce qui suit :

class User(object):
    def __init__(self):
        self.name = 'haibo'
        self.age = 23
def test():
    return User()
#初始化该延迟加载类
user = CommonLazyObject(lambda :test())
#此时我们要引用的类才执行
user.age = 28

J'ai défini une classe User ci-dessus, qui est la classe que nous voulons référencer dans le programme, et CommonLazyObject est la classe de chargement paresseux que nous avons définie (nous en parlerons plus tard). En chargeant paresseusement la classe, nous n'avons pas besoin de l'initialiser à l'avance. Elle ne sera instanciée que lorsque nous souhaitons effectuer des opérations telles que user.age ci-dessous.

D'accord, jetons un coup d'œil au processus d'implémentation spécifique de la classe de chargement paresseux.

Réflexion : notre opération d'instanciation se résumera en fin de compte à des opérateurs tels que __getattr__ et __setattr__. Par conséquent, tant que nous définissons ces opérateurs, nous pouvons atteindre ces délais, c'est-à-dire uniquement lorsque ces opérations sont effectuées, pour réellement instancier le. classe que nous voulons instancier :

#建立一个空的对象
empty = object()
#一个装饰器,对__getattr__进行装饰,使得其可以进行类的实例化
def proxy_getattr(func):
    def wrapper(self,*args):
        if self._wrapper is empty:
            self._init_object()
        return func(self._wrapper,*args)
    return wrapper
class LazyObject(object):
    def __init__(self):
        self._wrapper = empty
    __getattr__ = proxy_getattr(getattr)
        #进行赋值操作的时候,看是实例化类,还是对类的实例进行赋值操作。因为下面我们要进行实例化类的操作。
    def __setattr__(self, key, value):
        if key == '_wrapper':
            self.__dict__['_wrapper'] = value
        else:
            if self._wrapper is empty:
                self._init_object()
            setattr(self._wrapper,key,value)
        #在子类中,你应该重新定义它,你通过它,来实现你想要通过何种方式实例化你的类。
    def _init_object(self):
        pass

Regardez d'abord le __setattr__ ci-dessus. Lorsque nous effectuons l'opération d'affectation de user.age=28, cet opérateur sera appelé s'il n'y a pas de classe de retard Pour instancier la classe que nous voulons introduire. , nous allons d'abord l'instancier, c'est-à-dire appeler self._init_object et l'attribuer à _wrapper. Si l'instanciation est terminée, la méthode __setattr__ de l'instance sera exécutée immédiatement.​ ​

De même, __getattr_ est également le même. Si je veux imprimer user.name, je dois d'abord vérifier si la classe référencée a été instanciée. Sinon, instancier-la d'abord, puis appeler __getattr__ de l'instance.

D'accord, regardons une sous-classe qui implémente l'instanciation :

class CommonLazyObject(LazyObject):
    def __init__(self,func):
        self.__dict__['_wrapperfunc'] = func
        super(CommonLazyObject,self).__init__()
    def _init_object(self):
        self._wrapper = self._wrapperfunc()

Le processus d'instanciation de cette sous-classe est très simple, il suffit de l'appeler directement.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer