python 想實作延遲的操作是需要套用time ,然後在使用time的sleep 方法
例如我想寫一個延遲1秒列印一次的動作
import time for i in range(0, 10): time.sleep(1) print(i)
Python裡面的延遲載入用得非常多,其主要想法是延遲所要引入類別的實例化,節省一些初始化所需的時間和空間。
這種想法在Django中應用得也是非常廣泛,例如ORM的QuerySet,還有鑑權中間件中的request.user等等,這些都是利用了延遲載入的想法。
本文就是透過例子來分析延遲載入的想法。
實現延遲加載的基本思路是我創建一個類,我們將我們需要實例化的類傳給他,這時該類都會變成一個延遲加載類,在應用的時候,雖然我實例化了這個延遲載入類,但是我們要引用的類別就沒有實例化。
就像下面這樣:
class User(object): def __init__(self): self.name = 'haibo' self.age = 23 def test(): return User() #初始化该延迟加载类 user = CommonLazyObject(lambda :test()) #此时我们要引用的类才执行 user.age = 28
上面我定義了一個User類,它是我們在程式中要引用的類,CommonLazyObject是我們定義的延遲載入類別(後面再說)。透過延遲載入類,我們不必要地提前初始化它,只有我們想進行如下面的user.age的操作的時候,才會進行實例化。
好,下面看一下延遲載入類別的具體實作過程。
思想:我們對於一個實例化的操作,無非最終會歸結為__getattr__,__setattr__等運算符,因此只要我們定義好這些運算符就可以實現這些延遲,即只有執行這些操作的時候,才去真正實例化我們想要實例化的類別:
#建立一个空的对象 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
先看上面的__setattr__,當我們執行user.age=28的賦值操作的時候,就會呼叫該運算符,如果該延遲類別中並沒有實例化我們要引入的類,就會先進行實例化,即呼叫self._init_object,並賦值給_wrapper。如果已經實例化完成,那麼該實例的__setattr__方法就會立即執行。
同理,__getattr_也是一個道理,我想print user.name ,首先要檢查引用的類別是否已經實例化,如果沒有實例化就先實例化,然後再呼叫該實例的__getattr__ 。
好,再看一個實作實例化的子類別:
class CommonLazyObject(LazyObject): def __init__(self,func): self.__dict__['_wrapperfunc'] = func super(CommonLazyObject,self).__init__() def _init_object(self): self._wrapper = self._wrapperfunc()
這個子類別實例化的過程很簡單,就直接呼叫了。
以上是python之怎麼實現延遲操作的詳細內容。更多資訊請關注PHP中文網其他相關文章!