将全局变量传递给类和函数的替代方法

Flo*_*oul 2 python

我是Python新手,我一直在读到使用global将变量传递给其他函数被认为是菜鸟,也是一种不好的做法。我想不再使用全局变量,但我不知道该怎么做。

现在,我有一个在 wxPython 中创建的 UI 作为其自己的单独类,并且我有另一个从 .ini 文件加载设置的类。由于 UI 中的设置应与 .ini 中的设置相匹配,因此如何传递这些值?我可以使用类似:Settings = Settings()然后将变量定义为类似的东西self.settings1,但随后我必须创建Settings一个全局变量以将其传递给我的 UI 类(如果我在其中分配,则不会是这样main())。

那么传递这些变量的正确且Python式的方法是什么?

编辑:这是我正在使用的代码,我试图让它像 Alex Martelli 的示例一样工作。以下代码保存在Settings.py

import ConfigParser

class _Settings():
    @property
    def enableautodownload(self): return self._enableautodownload
    def __init__(self):
        self.config = ConfigParser.ConfigParser()

        self.config.readfp(open('settings.ini'))
        self._enableautodownload=self.config.getboolean('DLSettings', 'enableautodownload')

settings = _Settings()
Run Code Online (Sandbox Code Playgroud)

Settings.settings.enableautodownload每当我尝试从另一个文件引用时,我都会得到: AttributeError: 'module' object has no attribute 'settings'. 我究竟做错了什么?

编辑2:别介意这个问题,我重新输入了代码,现在它可以工作了,所以它一定是一个简单的拼写或语法错误。

Ale*_*lli 5

变量的替代方案global有很多——主要是:

  • 函数的显式参数、调用来创建其实例之一的类等(这通常是最清晰的,因为它使依赖关系最显式,在可行且不太重复的情况下);
  • 对象的实例变量,当需要访问这些值的函数是同一对象上的方法时(这也可以,并且是使用 OOP 的合理方法);
  • 提供值的“访问器函数”(或具有值的属性或属性的对象)。

其中每一个(尤其是第一个和第三个)对于其名称不得所有人重新绑定而只能访问的值特别有用。真正的大问题global是它提供了一个“隐蔽的通信通道”(不是密码学意义上的,而是字面意义上的:表面上独立的函数实际上可以通过全局值相互依赖,相互影响,而这些全局值不是“从函数的签名中显而易见”——这使得代码难以测试、调试、维护和理解)。

对于您的具体问题,如果您从不使用该global语句,而是从任何地方以“只读”方式访问设置(并且您可以通过使所述对象的属性成为只读属性来更充分地确保这一点!),那么在单个、一次制作后不更改的模块级实例上执行“只读”访问还不错。即,在某些模块中foo.py

class _Settings(object):
    @property
    def one(self): return self._one
    @property
    def two(self): return self._two
    def __init__(self, one, two):
       self._one, self._two = one, two
settings = _Settings(23, 45)
Run Code Online (Sandbox Code Playgroud)

以及从其他任何地方,import foo然后根据需要进行foo.settings.one访问。foo.settings.two请注意,我用一个前导下划线命名该类(就像只读属性下面的两个实例属性一样),以表明它不应该从模块“外部”使用 - 只假设该settings对象(没有强制执行——但任何违反此类要求的隐私的用户显然是对可能发生的任何混乱负责的唯一一方;-)。