Python 3中全局变量的正确使用方法

58
在Python 3中,全局变量的正确使用方法是什么?
1)在核心脚本(不在函数内部)中一次声明global VAR_NAME,然后在其他所有地方简单地将变量称为VAR_NAME 2)在每个使用全局变量的函数中一次声明global VAR_NAME,然后在函数余下的部分和核心脚本自身中简单地引用变量VAR_NAME

2
回应Rik的观点,更重要的问题是什么让你认为你需要它?初学者使用global关键字几乎总是表明试图使用其他语言的思维方式进行编程,如果你正在阅读一些鼓励使用它的教程,那么你需要找到更好的教程。 - DSM
只有第二点是相关的。你不能全局声明一个全局变量。你必须在每个将引用全局变量的本地命名空间中更改名称的含义。当你尝试第一种方法时,它是否有效?如果有效,你能举个例子证明吗?另外,避免使用全局变量。 - S.Lott
3
除了其他人提到的不使用全局变量,您可以通过尝试两种方法中的任意一种来轻松找出哪种方法可行。 - Thomas K
4个回答

73
在第一种情况下,全局关键字是无意义的,因此这不正确。在模块级别定义变量会将其变为全局变量,您不需要使用全局关键字。
第二个示例是正确的用法。
然而,最常见的全局变量用法是在函数/方法中没有使用全局关键字。只有当您想要重新分配全局变量时才需要使用全局关键字。

谢谢,这帮助我弄清楚了如何将模块用作单例而不是为其创建一个类。我没有意识到在函数内部不应该重新分配模块级变量。 - Dagrooms
2
我没有给这个回答点踩,但是我发现了一个问题:OP的第二个例子实际上是不正确的:在函数内部,只有当函数要给全局变量赋值时才需要使用global关键字。如果函数只是引用(读取)全局变量,则不需要使用global关键字。 - FKEinternet

64

如果您在函数中使用全局变量的方式被解释为对局部变量的赋值,您需要在该函数中使用global关键字。如果没有使用global关键字,将会在函数范围内创建一个隐藏全局变量的局部变量。

以下是一些示例:

global_var = 1

def example1():
    # global keyword is not needed, local_var will be set to 1.
    local_var = global_var

def example2():
    # global keyword is needed, if you want to set global_var,
    # otherwise you will create a local variable.
    global_var = 2

def example3():
    # Without using the global keyword, this is an error.
    # It's an attempt to reference a local variable that has not been declared.
    global_var += 1

7

"在其他情况下可能会被解释为对本地变量的赋值" --- 是的,但这里有一个微妙的细节:

------------------- 错误:在赋值之前引用了本地变量'c'

def work():
  c += 3

c = 0

work()
print(c)

-------------------错误:在赋值之前引用了本地变量'c'

c = 0

def work():
  c += 3

work()
print(c)

------------------- 打印 [3]

def work():
  c.append(3)

c = []

work()
print(c)

------------------- 打印 [3]

c = []

def work():
  c.append(3)

work()
print(c)

这是因为在你后面的两个例子中,你引用了一个方法,而不是分配一个变量。你需要使用全局关键字来给全局变量赋值。你可以在没有全局关键字的情况下引用它。 - Scone

1
上述答案中前两种情况和后两种情况的主要区别在于列表是可变的。对于像a = 1这样的情况,指针指向1所在的位置,当您说a = 2时,指针会移动。
对于可变对象的情况,会分配一个内存位置,当使用append等方法时,更改会发生在内存位置本身,因此可变引用的值会全局更改。
现在的关键问题是函数如何知道我们修改的变量是全局的还是局部的,因为如果它是可变的,则似乎我们可以修改全局变量,如果它是不可变的,则不能(函数也不将其识别为全局变量)。

你的“大问题”是谬误的。在最后两种情况中,函数知道变量是全局的,因为它__没有__被修改。这些函数中没有赋值c = ...。变量c保留相同的引用。c所指的对象被修改了,但c本身没有被修改。我认为这就是区分前两个和后两个例子的关键。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接