在类和函数间传递全局变量的替代方案
我刚开始学习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()
每当我尝试从另一个文件引用Settings.settings.enableautodownload
时,我都会得到:AttributeError: 'module' object has no attribute 'settings'
。我哪里做错了?
编辑2:没事了,我重新输入了一遍代码,现在可以用了,可能只是简单的拼写或语法错误。
1 个回答
关于global
变量,有很多替代方案,主要有以下几种:
- 给函数、类传递明确的参数,比如在创建实例时传入的参数(这种方式通常最清晰,因为它让依赖关系变得非常明确,只要不是太重复就好);
- 对象的实例变量,当需要访问这些值的函数是该对象的方法时(这也是可以的,是使用面向对象编程的合理方式);
- 提供值的“访问函数”,或者是有属性或特性的对象。
这些方法(尤其是第一和第三种)特别适合那些名称不能被随意重绑定的值,而只能被访问。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)
然后在其他地方,import foo
,再根据需要访问foo.settings.one
和foo.settings.two
。注意,我给类命名时加了一个下划线(就像这两个只读属性的实例属性一样),这表示它不应该从模块“外部”使用——只有settings
对象应该被使用(这并没有强制执行——但任何违反这种隐私请求的用户显然要对可能发生的混乱负责;-)。