延遲加載 lazy loading的粗略定義:第一次使用到某一個屬性的時候再加載真正的內(nèi)容到內(nèi)存踩身。
使用場景:
比如你需要在代碼的某一步驟讀一個巨大的CSV胀茵,耗時很長,所以你希望在用到此CSV內(nèi)容的時候再進行具體讀的操作挟阻,因為對于這個工程來說你可能有100個大型CSV待用琼娘,你需要先創(chuàng)建這些數(shù)據(jù)的對象呵哨,但具體的文件內(nèi)容 attribute 你在沒調(diào)用的時候不需要,你想先留一個空的 attribute轨奄。
一般人都喜歡在延遲加載中用@property
來實現(xiàn) "用一個方法表示屬性"這個目的孟害。
實現(xiàn):
在類的第一行創(chuàng)建一個為None的變量,在方法content
里調(diào)用真正的讀寫操作reading_csv
方法挪拟。這個 return 是關(guān)鍵挨务,它的存在會使得最初的變量不再是None,因此 if 判斷只會為真一次玉组,如截圖所示谎柄,第二次再調(diào)用 content 時就不會再運行reading_csv
方法了。
@property
可以把方法變?yōu)閷傩裕篶ontent雖然為一個方法惯雳,但是當(dāng)我調(diào)用的時候沒有打結(jié)尾的括號朝巫,而是直接 g.content
,這樣從人眼閱讀角度要更為直白石景。不過你當(dāng)然也可以就寫一個普通的類方法劈猿,但是名字可能就要改為 get_content() 更準(zhǔn)確一些。
使用@property
的好處還有一點潮孽,假如別人已經(jīng)在工程其他地方用過你這個類的 value = object.content 了揪荣,你是后來才需要寫這個動態(tài)加載的,那如果你再寫一個 get_content() 方法往史,其他用過的地方全都要改成 value = get_content(), 哪怕你用屬性的原名content來命名這個新方法仗颈,你也最起碼要在其他使用的地方加上括號變成 value = object.content(),而使用@property來把一個原有的attribute改為方法不會影響其他地方的使用椎例,因為語法不變挨决。
import time
class my_csv():
_default_instance = None
def __init__(self, csv):
self.csv = csv
def reading_csv(self):
print("Taking 2s to read a big csv")
time.sleep(2)
return "I am the content"
@property
def content(self):
if not self._default_instance:
self._default_instance = self.reading_csv()
return self._default_instance