Stack Overflow 有很多关于 python 中的全局变量的问题,它似乎给来自其他语言的人们带来了一些困惑。范围界定规则并不完全按照许多来自其他背景的人所期望的方式发挥作用。
同时,代码不应该在类级别上组织,而是在模块级别上组织。因此,当所有内容不一定包含在类中时,原本在成员变量中找到的状态可以放入模块级变量中。
所以我的问题分为两部分:
1)我应该避免使用全局变量(特别是在函数内设置它们并使用 global 关键字)?
2)如果#1是肯定的,是否有预期使用它们的常见模式?
我在一个充斥着许多不同语言的地方工作,我想减少混乱并确保 Python 爱好者以后不会讨厌我。
感谢您提供任何建设性意见。
我强烈建议您阅读这篇题为“Python 中的单例及其问题 http://lucumr.pocoo.org/2009/7/24/singletons-and-their-problems-in-python/。它让我重新思考我对全局变量的使用。一些选择引用:
但要小心。仅仅因为您没有实现单例设计模式,并不意味着您避免了单例的核心问题。单例的核心问题是全局共享状态。单例只不过是一个美化的全局变量,在像 Java 这样的语言中,有很多原因导致你想要使用像单例这样的东西。在 Python 中,我们对单例有一些不同的东西,它有一个非常无辜的名字,隐藏了血淋淋的细节:模块。
伙计们,这是对的:Python 模块是一个单例。它和单例模式有同样的问题,只是稍微差一点。
以下是具有这种共享状态可能导致的问题的一个示例:
为了不谈论无关紧要的事情,让我们看一下标准库中的模块之一,mimetypes 模块。
看一看:
inited = False
def init(files=None):
global inited
db = MimeTypes()
...
这是来自 Python 附带的 mimetypes 模块的实际代码,只是删除了更多血淋淋的细节。关键是,存在共享状态。共享状态是一个布尔标志,如果模块已初始化,则为 True;如果未初始化,则为 False。现在,这种特殊情况可能不是那么有问题(相信我,确实如此),因为 mimetypes 会自行初始化,但您可以看到 init 函数有一个 files 参数。如果将文件列表传递给该函数,它将使用这些文件中的 mime 信息重新初始化内存中的 mime 数据库。现在想象一下,如果你有两个库用两个不同的源初始化 mimetypes,会发生什么......
这是一个足够常见的模式,我自己也做过......但例如更好的方法是:init
返回一个实现了所有方法的类的实例,其他部分的代码可以init
获得具有不同参数的不同实例,这些参数不会干扰前者。 “缺点”是您必须将此实例传递给任何不想初始化新实例的代码,但“缺点”的优点是它使您的依赖项变得显而易见。
无论如何,简而言之,我会尽力避免它,但如果您可以接受具有隐式单例的代码,那么就使用它。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)