在模块中初始化变量的最佳方法



假设我需要将传入的数据写入云上的数据集中。何时,何处以及是否需要代码中的数据集,取决于进来的数据。我只想获得一次对数据集的引用。实现这一目标的最佳方法是什么?

  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. 首次需要数据集,并将其保存为函数属性,并使用get_dataset()方法访问

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

做您想做的事情的典型方法是包装服务,要求数据进入类:

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

然后,您将其实例化一次在您的主体中,并在需要的任何地方使用。

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变量是内部的,但可以通过可发现的函数访问。您也可以在类的实例上使用property

另外,使用对象和类使在大型项目中更加清楚,因为该功能应该从类别和方法中自称。

请注意,您也可以轻松地使其成为通用服务,并将其传递给初始化中的数据(如URL?),因此可以用不同的端点重新使用。

要避免的一个警告是在您的子模型中多次实例化相同的类,而不是主编码。如果这样做,则将为每个实例获取并存储数据。另一方面,您可以将类的实例传递给子模块,并且只能在需要时获取数据(即,如果您的子模块不需要,可能永远不会获取它),而使用所有选项,则数据集需要先获取其他地方。

注意您提出的选项:

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

如果您将模块称为模块,则不会在全球初始初始化(仅在调用shell调用模块时会初始化)。

即使您不需要Main。

  1. 在函数中设置全局。

通常不建议使用global,就像任何编程语言一样。从范围中修改变量是遇到奇数行为的食谱。如果您依靠仅在特定工作流程中设置的全局,它也倾向于使代码更难测试。

  1. 函数上的属性

这是一种眼神:它肯定会起作用,并且功能与我提出的Class模式非常相似,但是您必须接受功能上的属性。类的优点是,您可以以多种方式将其初始化,可以将其子类等起来,却不能在需要之前获取数据。使用直函数是"更简单",但更有限。

您也可以使用functools模块中的lru_cache装饰器来实现仅运行一次昂贵操作的目标。

只要参数相同,请一次又一次调用函数。

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

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

类似于MRE的答案,最好用包装器将数据封装。

但是,我建议您使用python闭合python闭合而不是类。

应该使用类来封装与数据密切相关的数据和相关功能。一个类应该是您将实例化对象的东西,并且对象将保留个性。您可以在此处阅读有关此信息的更多信息

您可以使用以下方式使用封闭

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()()

相关内容

  • 没有找到相关文章

最新更新