python之如何實現(xiàn)延遲操作
python實現(xiàn)延遲操作
python 想實現(xiàn)延遲的操作是需要應(yīng)用time ,然后在使用time的sleep 方法
比如我想寫一個延遲1秒打印一次的操作
import time for i in range(0, 10): time.sleep(1) print(i)
Python延遲加載問題
Python里面的延遲加載用得非常多,其主要思想是延遲所要引入類的實例化,節(jié)省一些初始化所需要的時間和空間。
這種思想在Django中應(yīng)用得也是非常廣泛,比如ORM的QuerySet,還有鑒權(quán)中間件中的request.user等等,這些都是利用了延遲加載的思想。
本文就是通過例子來分析延遲加載的思想。
實現(xiàn)延遲加載的基本思路是我創(chuàng)建一個類,我們將我們需要實例化的類傳給他,這時該類都會變成一個延遲加載類,在應(yīng)用的時候,雖然我實例化了這個延遲加載類,但是我們要引用的類就沒有實例化。
就像下面這樣:
class User(object): ?? ?def __init__(self): ?? ??? ?self.name = 'haibo' ?? ??? ?self.age = 23 def test(): ?? ?return User() #初始化該延遲加載類 user = CommonLazyObject(lambda :test()) #此時我們要引用的類才執(zhí)行 user.age = 28
上面我定義了一個User類,它是我們在程序中要引用的類,CommonLazyObject是我們定義的延遲加載類(后面再說)。通過延遲加載類,我們不必要提前初始化它,只有我們想進行如下面的user.age的操作的時候,才會進行實例化。
好,下面看一下延遲加載類的具體實現(xiàn)過程。
思想:我們對于一個實例化的操作,無非最終會歸結(jié)為__getattr__,__setattr__等運算符,因此只要我們定義好這些運算符就可以實現(xiàn)這些延遲,即只有執(zhí)行這些操作的時候,才去真正實例化我們想要實例化的類:
#建立一個空的對象 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) ? ? ? ? #在子類中,你應(yīng)該重新定義它,你通過它,來實現(xiàn)你想要通過何種方式實例化你的類。 ?? ?def _init_object(self): ?? ??? ?pass
先看上面的__setattr__,當(dāng)我們執(zhí)行user.age=28的賦值操作的時候,就會調(diào)用該運算符,如果該延遲類中并沒有實例化我們要引入的類,就會先進行實例化,即調(diào)用self._init_object,并賦值給_wrapper。如果已經(jīng)實例化好了,就會直接進行這個實例的__setattr__。
同理,__getattr_也是一個道理,我想print user.name ,首先要檢查引用的類是否已經(jīng)實例化,如果沒有實例化就先實例化,然后再調(diào)用該實例的__getattr__。
好,再看一個實現(xiàn)實例化的子類:
class CommonLazyObject(LazyObject): ?? ?def __init__(self,func): ?? ??? ?self.__dict__['_wrapperfunc'] = func ?? ??? ?super(CommonLazyObject,self).__init__() ?? ?def _init_object(self): ?? ??? ?self._wrapper = self._wrapperfunc()
這個子類實例化的過程很簡單,就直接調(diào)用了。
OK!上面就介紹了延遲加載的思想以及創(chuàng)建過程??赡埽艺f的是最基本的實現(xiàn)方法,但也是Django中經(jīng)常用的。
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
Python?pandas找出、刪除重復(fù)的數(shù)據(jù)實例
在面試中很可能遇到給定一個含有重復(fù)元素的列表,刪除其中重復(fù)的元素,下面這篇文章主要給大家介紹了關(guān)于Python?pandas找出、刪除重復(fù)數(shù)據(jù)的相關(guān)資料,文中通過實例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-07-07