2017-04-03 181 views
0

我來自C++背景,經常使用靜態變量減少時間變量必須初始化的次數(特別是初始化需要很長時間時)。Python - 靜態類變量

class MyClass(object): 

    StaticList1 = [...] # Very large list 
    StaticList2 = [...] # Very large list 

現在,這是好的,如果存在的MyClass至少1個實例整個程序的執行和列表只能創建一次:所以從StackOverflow上其他的帖子,人們使用靜態類變量如下建議。但是,如果在執行的某個階段沒有MyClass的實例,Python似乎刪除了靜態列表(我假設,因爲參考計數器下降到0)。

所以我的問題,有沒有簡單的方法,沒有使用外部模塊來初始化StaticList1和StaticList2一次(他們第一次使用),並永遠不會刪除他們,即使沒有MyClass的實例,直到該程序存在(或者您手動刪除列表)?

編輯:

也許我過分簡化了這個問題。我在做什麼:

class MyClass(object): 

    StaticList = None 

    def __init__(self, info): 
     if self.StaticList == None: 
      print "Initializing ..." 
      self.StaticList = [] 
      # Computationally expensive task to add elements to self.StaticList, depending on the value of parameter info 

    def data(self): 
     return self.StaticList 

我從另一個腳本導入模塊,並有一個循環是這樣的:

import myclass 
for i in range(10000): 
    m = myclass.MyClass(i) 
    d = m.data() 
    # Do something with d. 

靜態列表的初始化大約需要200 - 300毫秒,在執行上循環的每一次迭代,因此循環需要非常長的時間才能完成。

+3

你可以利用模塊是單身的事實,所以如果你創建這些模塊級別的成員,只要模塊被導入並且只存在一次,它們就會一直存在。 –

+1

這聽起來不錯,我不希望那些名單去任何地方。 你在說你正在調用'MyClass.StaticList1 ...',你得到一個錯誤?你遇到了什麼錯誤? – gbtimmon

+0

*但是,如果在執行的某個階段沒有MyClass的實例,Python似乎刪除了靜態列表* AFAIK,這是錯誤的。該類將獨立存在於該類的對象中,並且在類級別定義的所有屬性將通過該類繼續存在。你能舉一個你的問題的例子嗎? –

回答

2

當你的類確實有一個叫StaticList靜態字段,你實際上是初始化和處理,因爲您使用的是self預選賽的同名實例字段工作。如果您使用MyClass.StaticList來初始化並訪問它,我認爲您的代碼將正常工作。

一般來說,Python的名稱查找,您可以通過一個實例該實例訪問類領域,如果它是一個實例字段(例如,self.StaticList)只要你還沒有真正建立一個實例字段該實例中的同名名稱。從那一刻開始,實例字段會隱藏類字段(即,self.StaticList將會找到您的新值,而MyClass.StaticList仍然會引用您的類值)。

由於從解釋新鮮的例子:

>>> class A(object): 
... v=2  # static initialization 
... 
>>> A.v 
2 
>>> a=A()  # get an instance, and 
>>> a.v  # get the static value via the instance: 
2 
>>> a.v = 7 # but now set 'v' on the instance, and ... 
>>> a.v  # we will get the instance field's value: 
7 
>>> A.v  # the static value is still the old: 
2 
>>> b=A()  # and other instances of the class ... 
>>> b.v  # will use the same old static value: 
2 

實例變量a.v最初等於A.v,但通過顯式設置a.v=7,你在這個實例「分離」出來。

雖然這意味着,原則上,你可以使使用靜態類字段MyClass.Values以及同名的實例字段xyz.Values,這往往是望而卻步的正是這種混亂的。

作爲一個獨立的話,你可以考慮註解data方法作爲@staticmethod(和刪除中招self參數),並把它作爲MyClass.data()使事實更加清晰,你會在找回同一列表實例每個電話。

+0

這聽起來很合邏輯,如果不是這樣的話:我一直在使用self.StaticVar來處理一堆其他類,其中靜態var在聲明中直接被初始化,而不是構造函數。如果我然後在類的某處打印self.StaticVar,則將打印var的值。因此,在這種情況下,似乎MyClass.StaticVar與self相同.StaticVar – goocreations

+0

我已經擴展瞭解決這方面問題的邏輯。 :) – Hans