2

我正在处理我的第一个重要的 Python 项目,但在范围问题和在包含的文件中执行代码时遇到了麻烦。以前我的经验是使用 PHP。

我想做的是有一个文件来设置许多配置变量,然后将在整个代码中使用这些变量。另外,我想让某些函数和类在全球范围内可用。例如,主文件将包含一个其他文件,该文件将加载一堆常用函数(每个函数都在自己的文件中)和一个配置文件。在这些加载的文件中,我还希望能够访问函数和配置变量。我不想做的是必须将整个例程放在每个(包含)文件的开头以包含所有其余部分。此外,这些包含的文件位于各种子目录中,这使得导入它们变得更加困难(特别是如果我必须在每个文件中重新导入)。

无论如何,我正在寻找有关构建代码以实现我想要的最佳方式的一般建议。

谢谢!

4

4 回答 4

6

在 python 中,通常的做法是拥有一堆实现各种功能的模块,然后拥有一个模块作为所有功能的访问点。这基本上是门面模式

一个例子:假设你正在编写一个包foo,其中包括barbazmoo模块。

~/project/foo
~/project/foo/__init__.py
~/project/foo/bar.py
~/project/foo/baz.py
~/project/foo/moo.py
~/project/foo/config.py

你通常会这样写__init__.py

from foo.bar import func1, func2
from foo.baz import func3, constant1
from foo.moo import func1 as moofunc1
from foo.config import *

现在,当你想使用你刚刚做的功能时

import foo
foo.func1()
print foo.constant1
# assuming config defines a config1 variable
print foo.config1

如果你愿意,你可以安排你的代码,这样你只需要编写

import foo

在每个模块的顶部,然后通过foo它访问所有内容(您可能应该将其命名为“全局”或类似的名称)。如果你不喜欢命名空间,你甚至可以这样做

from foo import *

并将一切都作为全球性的,但这真的不推荐。请记住:命名空间是一个很棒的主意!

于 2009-02-03T15:36:21.187 回答
1

这是一个两步过程:

  1. 在您的模块 globals.py 中,从任何地方导入项目。
  2. 在所有其他模块中,执行“从全局导入 *”

这会将所有这些名称带入当前模块的命名空间。

现在,已经告诉你如何做到这一点,让我建议你不要这样做。首先,您正在使用一堆“神奇定义”的实体加载本地名称空间。这违反了 Python 之禅的戒律 2 ,“显式胜于隐式”。尝试使用“import foo”,然后说“foo.some_value”,而不是“from foo import *”。如果您想使用较短的名称,请使用“from foo import mumble, snort”。这些方法中的任何一个都直接暴露了模块 foo.py 的实际使用。使用 globals.py 方法有点太神奇了。主要的例外是在 __init__.py 中,您在其中隐藏了包的一些内部方面。

全局变量也是半邪恶的,因为很难弄清楚谁在修改(或破坏)它们。如果您有明确定义的获取/设置全局变量的例程,那么调试它们会简单得多

我知道 PHP 有这种“一切都是一个、大、快乐的命名空间”的概念,但它实际上只是糟糕的语言设计的产物。

于 2009-02-03T15:36:36.850 回答
0

据我所知,程序范围的全局变量/函数/类/等。在 Python 中不存在,所有内容都“限制”在某个模块(命名空间)中。因此,如果您希望在代码的许多部分中使用某些函数或类,一种解决方案是创建一些模块,例如:“globFunCl”(​​从其他地方定义/导入您想要成为“全局”的所有内容)和“config”(包含配置变量)并在需要它们的任何地方导入它们。如果您不喜欢使用嵌套命名空间的想法,您可以使用:

from globFunCl import *

这样,您将“隐藏”命名空间(使名称看起来像“全局”)。

我不确定您不想“将整个例程放在每个(包含的)文件的开头以包含所有其余部分”的意思,恐怕您无法真正摆脱这一点。不过,请查看Python 包,它们应该会让您更轻松。

于 2009-02-03T15:35:06.933 回答
0

这在一定程度上取决于您希望如何打包。您可以考虑文件模块。后者是“更 Pythonic”,使您能够准确地决定哪些项目(它们可以是任何具有名称的项目:类、函数、变量等)要使其可见。

基本规则是,对于您导入的任何文件或模块,可以直接访问其命名空间中的任何内容。因此,如果 myfile.py 包含定义def myfun(...):class myclass(...)那么myvar = ...您可以通过以下方式从另一个文件访问它们

import myfile
y = myfile.myfun(...)
x = myfile.myvar

或者

from myfile import myfun, myvar, myclass

至关重要的是,可以访问 myfile 顶层的任何内容,包括导入。所以如果 myfile 包含from foo import bar, thenmyfile.bar也是可用的。

于 2009-02-03T15:47:01.823 回答