我正试图了解为什么在Python(以及编程普遍情况下),使用global
被认为是不良实践。有人可以解释一下吗?也欢迎提供更多信息的链接。
我正试图了解为什么在Python(以及编程普遍情况下),使用global
被认为是不良实践。有人可以解释一下吗?也欢迎提供更多信息的链接。
这与Python无关;在任何编程语言中,全局变量都不好。
然而,全局常量在概念上并不同于全局变量;全局常量是完全无害的。在Python中,两者之间的区别纯粹是按照惯例:CONSTANTS_ARE_CAPITALIZED
和globals_are_not
。
全局变量不好的原因在于它们使函数具有隐藏(不明显、令人惊讶、难以检测、难以诊断)的副作用,导致复杂性增加,可能导致意大利面条代码。
然而,在函数式编程中,合理使用全局状态(以及本地状态和可变性)是可以接受的,无论是为了算法优化、降低复杂性、缓存和备忘,还是将源自主要命令式代码库的结构移植到实践中。
总之,你的问题可以有很多种回答,所以最好的办法就是去谷歌搜索“为什么全局变量不好”。以下是一些示例:
如果你想更深入地了解为什么副作用很重要以及许多其他启发性的事情,你应该学习函数式编程:
理论上讲,全局变量和“状态”(state)总是不好的,但事实上,如果你查看Python包目录,你会发现大多数模块都以一堆全局声明开始。显然,人们对此没有问题。
具体来说,对于Python而言,全局变量的可见性仅限于模块,因此没有影响整个程序的“真正”的全局变量-这使得它们更少有害。另一个要点是:没有const
,因此当需要常量时,必须使用全局变量。
在我的实践中,如果我在函数中修改全局变量,我总是使用global
进行声明,即使在技术上并不需要,例如:
cache = {}
def foo(args):
global cache
cache[args] = ...
这使得全局变量的操作更容易被追踪。个人意见是,在函数逻辑中使用全局变量意味着其他代码可以更改该函数的逻辑和预期输出,这将使调试非常困难(尤其是在大型项目中),同时也会使测试更加困难。
此外,如果考虑其他人阅读您的代码(开源社区、同事等),他们将很难理解全局变量的设置位置、更改位置以及从这个全局变量中期望什么,而不是通过阅读函数定义本身来确定其功能的独立函数。
我认为,一个干净且(几乎)无错误的代码应该具有尽可能纯粹的函数(参见纯函数)。纯函数具有以下条件:
使用全局变量至少违反了上述条件之一,如果不是两者都违反了。因为外部代码可能会导致意想不到的结果。
另一个明确的纯函数定义是:“纯函数是一个将所有输入作为显式参数,并生成所有输出作为显式结果的函数。”[1]。使用全局变量违反了纯函数的理念,因为未显式给出或返回一个输入和可能的一个输出(即全局变量)。
如果考虑单元测试和F.I.R.S.T原则(快速测试、独立测试、可重复、自验证和及时)的话,很可能会违反独立测试原则(这意味着测试不依赖于其他测试)。
全局变量(并非总是如此,但至少在我目前所见的大多数情况下)用于准备和传递结果给其他函数。这也违反了这个原则。如果全局变量被用于这种方式(即函数X中使用的全局变量必须先在函数Y中设置),这意味着要对函数X进行单元测试,你必须先运行测试/运行函数Y。
另一方面,正如其他人已经提到的那样,如果全局变量用作“常量”,可能会稍微好一些,因为语言不支持常量。然而,我总是更喜欢使用类并将“常量”作为类成员,而不是使用全局变量。如果您有一个需要两个不同类共享全局变量的代码,则可能需要重构您的解决方案并使您的类彼此独立。
我不相信全局变量不能使用。但是,如果它们被使用,作者应该考虑一些原则(也许包括上述原则和其他软件工程原则和最佳实践),以获得更清洁和几乎没有错误的代码。
它们是必需的,屏幕就是一个很好的例子。然而,在多线程环境或涉及许多开发人员的情况下,实际上常常会出现一个问题:谁设置或清除了它(错误地)?根据架构,分析可能是昂贵的,并且经常需要。虽然读取全局变量可能没问题,但写入必须受控制,例如通过单个线程或线程安全类。因此,全局变量引起了高开发成本的担忧,这可能是它们自身被认为是邪恶的后果。因此,通常最好将全局变量数量保持在较低水平。