为什么全局变量是邪恶的?

问题描述 投票:82回答:4

我试图找到一个很好的来源,解释为什么在python(以及一般的编程)中使用global被认为是不好的做法。有人可以指点我或解释一下吗?

python global-variables side-effects
4个回答
122
投票

这与Python无关;全局变量在任何编程语言中都很糟糕。

但是,全局常量在概念上与全局变量不同;全局常量完全无害。只是在Python中没有强制差异,只有按惯例才有CONSTANTS_CAPITALIZEDglobals_are_not

他们不好的原因是他们允许功能隐藏(非显而易见,令人惊讶,难以察觉)的副作用,导致复杂性增加,可能导致Spaghetti code

然而,即使在函数式编程中,对于全局状态的合理使用也是可接受的(如本地状态和可变性),无论是算法优化,降低复杂性,缓存和存储,还是源自主要命令式代码库的移植结构的实用性。

总而言之,您的问题可以通过多种方式得到解答,因此您最好的选择就是谷歌“为什么全局变量都不好”。一些例子:

如果你想深入了解副作用的原因,以及许多其他有启发性的东西,你应该学习功能编程:


28
投票

是的,从理论上讲,全局(和一般的“状态”)是邪恶的。实际上,如果你查看python的packages目录,你会发现大多数模块都以一堆全局声明开头。显然,人们对他们没有任何问题。

特别是对于python,全局变量的可见性仅限于一个模块,因此没有影响整个程序的“真正”全局变量 - 这使得它们的危害性降低。另一点:没有const,所以当你需要一个常数时,你必须使用全局。

在我的实践中,如果我碰巧在函数中修改了一个全局函数,我总是用global声明它,即使技术上不需要它,如:

cache = {}

def foo(args):
    global cache

    cache[args] = ...

这使得全局变量的操作更容易被追踪。


9
投票

关于该主题的个人观点是,在函数逻辑中使用全局变量意味着某些其他代码可以改变该函数的逻辑和预期输出,这将使调试非常困难(特别是在大项目中)并且将使测试更难同样。

此外,如果您考虑其他人阅读您的代码(开源社区,同事等),他们将很难尝试了解全局变量的设置位置,已更改的位置以及对此全局变量的期望通过读取函数定义本身可以确定其功能的隔离函数。

(可能)违反Pure Function定义

我相信一个干净的(几乎)无错误的代码应该具有尽可能纯的函数(参见pure functions)。纯函数是具有以下条件的函数:

  1. 在给定相同参数值的情况下,该函数始终评估相同的结果值。功能结果值不能依赖于程序执行过程中或程序执行不同时可能发生的任何隐藏信息或状态,也不依赖于I / O设备的任何外部输入(通常见下文)。
  2. 对结果的评估不会导致任何语义上可观察到的副作用或输出,例如可变对象的突变或输出到I / O设备。

由于外部代码可能导致意外结果,因此全局变量违反了上述至少一项(如果不是两者)。

纯函数的另一个明确定义:“纯函数是一个函数,它将所有输入作为显式参数,并将其所有输出作为显式结果生成。” [1]。全局变量违反了纯函数的概念,因为输入可能没有明确地给出或返回输出之一(全局变量)。

(可能)违反单位测试F.I.R.S.T原则

此外,如果您考虑单元测试和F.I.R.S.T原则(快速测试,独立测试,可重复,自我验证和及时)可能违反独立测试原则(这意味着测试不依赖于彼此)。

拥有一个全局变量(并非总是)但在大多数情况下(至少我目前所见)是准备并将结果传递给其他函数。这也违反了这一原则。如果以这种方式使用全局变量(即函数X中使用的全局变量必须首先在函数Y中设置),则意味着要对单元测试函数X进行操作,首先必须运行测试/运行函数Y.

全局常数

另一方面,正如其他人已经提到的,如果全局变量被用作“常量”变量,则可能稍微好一点,因为该语言不支持常量。但是,我总是喜欢使用类并将“常量”作为类成员,而根本不使用全局变量。如果您有一个代码,两个不同的类需要共享一个全局变量,那么您可能需要重构您的解决方案并使您的类独立。

我不相信不应该使用全局变量。但是如果使用它们,作者应该考虑一些原则(上面提到的原则和其他软件工程原理和良好实践),以获得更清晰,几乎没有错误的代码。


3
投票

它们是必不可少的,屏幕就是一个很好的例子。但是,在多线程环境中或涉及许多开发人员的情况下,实际上常常会出现这样的问题:谁(确实)设置或清除了它?根据体系结构的不同,分析成本高昂且经常需要进行分析。虽然读取全局变量可以正常,但必须控制对它的写入,例如通过单个线程或线程安全类。因此,全球变量引发了对自身被认为是邪恶的后果可能导致高昂的开发成本的恐惧。因此,一般来说,将全球变量的数量保持在较低水平是一种很好的做法。

© www.soinside.com 2019 - 2024. All rights reserved.