簡體   English   中英

在模塊中初始化變量的最佳方法?

[英]Best way to initialize variable in a module?

假設我需要將傳入數據寫入雲上的數據集。 何時、何地以及是否需要代碼中的數據集,取決於傳入的數據。我只想獲得對數據集的一次引用。 實現這一目標的最佳方法是什么?

  1. 在啟動時初始化為全局變量並通過全局變量訪問

    if __name__="__main__": dataset = #get dataset from internet

這似乎是最簡單的方法,但即使從不需要它也會初始化變量。

  1. 首次需要數據集時獲取引用,保存在全局變量中,並使用get_dataset()方法訪問

    dataset = None def get_dataset(): global dataset if dataset is none dataset = #get dataset from internet return dataset
  2. 第一次需要數據集時獲取引用,保存為function屬性,通過get_dataset()方法訪問

    def get_dataset(): if not hasattr(get_dataset, 'dataset'): get_dataset.dataset = #get dataset from internet return get_dataset.dataset
  3. 任何其他方式

執行所需操作的典型方法是將調用數據的服務包裝到 class 中:

class MyService():
  dataset = None

  def get_data(self):
    if self.dataset = None:
      self.dataset = get_my_data()
    return self.dataset
    

然后你在你的 main 實例化它一次,並在你需要的地方使用它。

if __name__="__main__":

  data_service = MyService()
  data = data_service.get_data()
  # or pass the service to whoever needs it
  my_function_that_uses_data(data_service)

dataset變量是內部變量,但可通過可發現的 function 訪問。 您還可以在 class 的實例上使用property

此外,使用對象和類使其在大型項目中更加清晰,因為功能應該從類名和方法中不言自明。

請注意,您也可以輕松地將其設為通用服務,在初始化時將其傳遞給獲取數據的方式(如 url?),因此它可以與不同的端點重用。

要避免的一個警告是在子模塊中多次實例化相同的 class,而不是在主模塊中。 如果您這樣做了,將為每個實例獲取並存儲數據。 另一方面,您可以將 class 的實例傳遞給子模塊,並僅在需要時獲取數據(即,如果您的子模塊從不需要它,它可能永遠不會被獲取),而使用所有選項,數據集需要先獲取才能傳遞到其他地方。

請注意您提出的選項:

  1. if __name__ == '__main__'部分初始化:

如果您將模塊作為模塊調用,它不會全局初始化(它只會在從 shell 調用模塊時初始化)。

您需要獲取數據以將其傳遞到其他地方,即使您在 main 中不需要它。

  1. 在 function 中設置一個全局變量。

通常不鼓勵使用global ,因為它在任何編程語言中都是如此。 修改 scope 之外的變量是遇到奇怪行為的秘訣。 如果您依賴僅在特定工作流程中設置的這個全局變量,它也往往會使代碼更難測試。

  1. function 上的屬性

這個有點讓人眼花繚亂:它肯定會工作,並且功能與我建議的Class模式非常相似,但你必須承認函數的屬性不是很 Pythonic。 Class 的優點是您可以通過多種方式對其進行初始化,可以對其進行子類化等,但在您需要之前不獲取數據。 使用直接的 function 更“簡單”,但更有限。

您還可以使用functools模塊中的lru_cache裝飾器來實現僅運行一次昂貴操作的目標。

只要參數相同,一次次調用function返回相同的object。

https://docs.python.org/3/library/functools.html#functools.lru_cache

@lru_cache
def fun(input1, input2):
    ... # expensive operation
    return result

我一直發現這樣做的方法是您所說的第一號肉類。 對於聽起來像您想做的事,那將是您最好的肉類。

與 MrE 的回答類似,最好用包裝器封裝數據。

但是,我建議您使用python 閉合python 閉合而不是 class。

一個 class 應該用於封裝數據和與數據密切相關的相關功能。 class 應該是您將實例化對象並且對象將保留個性的東西。 您可以在此處閱讀有關此內容的更多信息

您可以通過以下方式使用閉包

def get_dataset_wrapper():
    dataset = None

    def get_dataset():
        nonlocal dataset
        if dataset is none
            dataset = #get dataset from internet
        return dataset
    return get_dataset

您可以通過以下方式使用它

dataset = get_dataset_wrapper()()

如果 ()() 語法困擾你,你可以這樣做:

def wrapper():
    return get_dataset_wrapper()()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM