31

Pylint W0603 状态:

使用全局语句。当您使用“global”语句更新全局变量时使用。PyLint 只是试图阻止这种用法。这并不意味着你不能使用它!

我想知道为什么会这样?有没有更多的 Pythonic 方式来修改函数内不可变的、模块范围的变量?是否建议将它们打包在字典等可变变量中?或者也许把整个模块变成类?

在我看来,当变量被建议为“私有”(以 _ 或 __ 为前缀)时,这个警告应该消失。

4

4 回答 4

35

全局变量的普遍使用会使维护成为一场噩梦,因为它们会跟踪程序的流程,有时会出现奇怪的错误,因为某些模块在其他模块更改变量值之前已经读取了变量并对其值采取了行动(这可能是由于在一些不相关的第三个模块中反转了两个 import 语句)。另请参阅关于全局变量的维基百科条目

这就是为什么你应该避免可变全局变量、IMO 以及为什么 Pylint 发出警告(并且可能应该发出更多警告。检测global关键字的使用只是发现其中一些的一种简单方法)。

不要误会我的意思:我并不是说你不能使用全局变量。只是你应该避免使用它们。Python 中有很多关于全局变量的合法案例。只要你没有得到超过几个 W0603,你应该可以接受。

现在,Logilab(维护 Pylint 的公司,也是我曾经工作的地方)曾经不得不接管超过 50kloc 的 Python 代码的维护工作,其中包含大量重复和 100 多个可变全局变量。这是地狱。

解决全局变量的解决方案包括:

  • 向需要访问变量的函数添加参数
  • 使用类属性
  • 使用实例属性(通过将您需要的值传递给类的构造函数)
  • 将可变全局值集中在构建的配置对象中,以便在程序启动时实例化一次(使用环境变量、命令行、配置文件......),此后永远不会发生变异。
于 2013-01-24T16:00:36.970 回答
13

我会替换这个:

the_file = None

def open_the_file(fname):
    global the_file
    the_file = open(fname)

def write_to_the_file(data):
    the_file.write(data)

open_the_file("boo")
write_to_the_file("Hi!")

有了这个:

class FileProgram(object):
    def __init__(self):
        self.the_file = None

    def open_the_file(fname):
        self.the_file = open(fname)

    def write_to_the_file(data):
        self.the_file.write(data)

if __name__ == "__main__":
    prog = FileProgram()
    prog.open_the_file("boo")
    prog.write_to_the_file("Hi!")

你可能会说,“这对我的简单任务来说太复杂了!” 好的,那么不要在你的程序上运行 pylint 。您不能要求 pylint 了解您的程序太小而无法使用良好的结构。

于 2013-01-24T16:18:48.853 回答
1

在 python 中,像这样共享全局数据的模块几乎是一个单例。你可以用一个singleton类来完成同样的事情,或者问问自己是否有任何理由真的需要一个单例。如果您不需要单例 - 使用常规类(实例)。如果您确实需要单例,请谷歌/搜索以确定您认为最适合您的模式。也许你确实想要一个模块 - 有一个利基global- 否则 Guido 很久以前就会从语言中删除它 - 这个利基恰好很小......

于 2013-01-24T15:07:53.277 回答
0

同意将其重构为类是方法。有一些特殊情况,类不是最优的,那么我建议使用 dataclass

from dataclasses import dataclass

@dataclass
class Files:
    the_file = "fname"

files = Files()

def open_the_file():
    files.the_file = "123"  # You can edit it here

这有一个很大的优势,如果你从其他模块导入它,它不是复制,而是引用,所以如果你在某处改变值,你仍然在任何地方得到正确的值。

But... usually making a class is the way. When to use this way? Personally I use it if I expect only one instance will ever exists (kind of singleton). Or if in public api (_init_.py) I want to use only the function to take the complexity out of the user.

于 2022-01-28T14:45:59.980 回答