如何用方法初始化Python中的modulelevel变量?

2024-04-24 11:05:54 发布

您现在位置:Python中文网/ 问答频道 /正文

在Java中,如果我想要“一个不变的变量,它可以用于类中的所有方法,而不作为参数传递”,我会这样做:

public class MyClass {
  private static final OtherClass OTHER_CLASS = buildOtherClass()

  ...

  private static OtherClass buildOtherClass() {
    //<creation logic>
  }

}

但是,如果我尝试在Python脚本中执行类似的操作,就会出现错误:

^{pr2}$

如果我将变量声明移到方法声明下面,代码将按预期运行。但是,对于代码的合法性依赖于元素的排序,我感觉很不直观,-方法存在于文件中,我不明白为什么不能找到它,仅仅因为它“还没有声明”。Moverover,将通用(非特定于方法的)变量放在文件顶部是一种代码约定,我觉得这是非常明智和有帮助的——“下面是我们将要处理的事情的概述”(尽管我想这在Python中并不那么正确,因为在Python中没有类型声明来提供额外的上下文)。在

我可以找到一些方法来解决这个问题,但没有一个在美学上是令人愉悦的:

  • 如上所述,我可以在变量之前声明方法。在
  • 我可以把构造函数方法放在一个辅助模块中,并将其导入到脚本中—我不喜欢这样做,因为提取可能只有几行代码的逻辑似乎太过分了。在
  • 我可以将这个脚本的逻辑放在Python类中,并在__init__方法中初始化变量。同样,这似乎是不必要的开销。在
  • 将变量设置为从__main__方法调用的方法中的全局变量,如下面的代码所示。不过,我已经看到很多指导意见,认为全球变量是一个危险信号,所以我想我也应该避免这种情况。在

(我需要将文本放在这里,否则下面的代码段是未格式化的,可能是因为上面的项目符号)

$ cat python_test_2.py
#!/usr/bin/env python3

def initializeGlobalVariables():
  global DICTIONARY
  DICTIONARY = {}
  for i in range(5):
    DICTIONARY[str(i)] = i

def doOtherLogic():
  for key in DICTIONARY:
    print('DICTIONARY[' + str(key) + '] is ' + str(DICTIONARY[key]))

def main():
  initializeGlobalVariables()
  doOtherLogic()

if __name__ == '__main__':
  main()
$ ./python_test_2.py
DICTIONARY[0] is 0
DICTIONARY[1] is 1
DICTIONARY[2] is 2
DICTIONARY[3] is 3
DICTIONARY[4] is 4

可能是因为我所要做的是完全不和谐的,所以缺乏支持是“出于设计”。我从一些经验丰富的用户那里得到了更多关于Python风格的反馈。在


Tags: 文件方法key代码脚本声明dictionaryis
1条回答
网友
1楼 · 发布于 2024-04-24 11:05:54

Python和Java在本质上是截然不同的语言,Python更像是一种脚本语言而不是编译语言(尽管它确实是在动态编译的)。而且,Python实际上并没有“不变变量…”的概念,至少没有通过变量名。变量名本质上是指向任何类型数据的指针(请参见:动态类型),如果没有特殊的python修饰符,您可以随时更改变量的值,有时会对您造成很大的损害。在

更重要的是,由于它的脚本性质(并且可以交互执行),事情的顺序很重要:

>>> def test():
...     print x
... 
>>> test()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in test
NameError: global name 'x' is not defined
>>> x = 1
>>> test()
1
>>> 

在本例中,函数test中的全局x只是一个指针,x不存在并不重要,因为您还没有尝试运行test。当来自强类型和编译语言时,这可能看起来与直觉相反,但它允许许多不错的功能,如动态导入,只在使用函数时加载模块:

^{pr2}$

如果每个变量都需要在函数内部使用之前被完全定义,那么定义dyn_import将失败,除非random被加载并且理解random.random()的含义。在这种情况下,直到函数实际执行时才加载它。另外,由于函数不会将模块放入脚本的全局命名空间中,因此一旦函数完成,模块就会被丢弃。在

这只是一个很重要的例子,说明这样做是非常有益的。在

相关问题 更多 >