我有这个:
g_c = 0
class TestClass():
global g_c
def run(self):
for i in range(10):
g_c = 1
print(g_c)
t = TestClass()
t.run()
print(g_c)
我如何才能真正修改我的全局变量 g_c?
通过global
在访问它的函数中声明它:
g_c = 0
class TestClass():
def run(self):
global g_c
for i in range(10):
g_c = 1
print(g_c)
Python 文档是这样说的,关于global
声明:
全局语句是适用于整个当前代码块的声明。
您需要global
在函数内移动声明:
class TestClass():
def run(self):
global g_c
for i in range(10):
g_c = 1
print(g_c)
该语句告诉 Python 编译器对该名称的任何分配(和其他绑定操作)都将更改全局命名空间中的值;默认设置是将分配给函数中任何位置的任何名称放在本地命名空间中。该声明仅适用于当前范围。
由于您从未g_c
在class body中分配 to,因此将语句放在那里没有任何效果。该global
语句仅适用于它所使用的范围,而不适用于任何嵌套范围。请参阅global
声明文档,该文档的开头为:
全局语句是适用于整个当前代码块的声明。
嵌套函数和类不是当前代码块的一部分。
我将在此处插入关于使用全局变量共享更改状态的强制性警告:不要这样做,这会使您的代码状态更难推理、更难测试、更难重构等。如果您必须共享一个改变单例状态(整个程序中的一个值)然后至少使用一个类属性:
class TestClass():
g_c = 0
def run(self):
for i in range(10):
TestClass.g_c = 1
print(TestClass.g_c) # or print(self.g_c)
t = TestClass()
t.run()
print(TestClass.g_c)
注意我们如何仍然可以从外部访问相同的值,命名空间到TestClass
命名空间。
我知道使用全局变量有时是最方便的事情,尤其是在使用类使最简单的事情变得如此困难的情况下(例如,multiprocessing
)。我在声明全局变量时遇到了同样的问题,并通过一些实验解决了这个问题。
g_c
类中的函数未更改的原因是对run
内部全局名称的引用g_c
并未在函数中精确建立。Python 处理全局声明的方式实际上是相当棘手的。该命令global g_c
有两个作用:
"g_c"
将键输入到内置函数可访问的字典中的前提条件, globals()
. 但是,在为其分配值之前,该键不会出现在字典中。
(可能)改变 Pythong_c
在当前方法中查找变量的方式。
对 (2) 的全面理解特别复杂。首先,它只是潜在地改变,因为如果g_c
在方法中没有对名称进行赋值,那么 Python 默认会在globals()
. 这实际上是一件相当普遍的事情,就像在代码开头一直导入的方法模块中引用的情况一样。
但是,如果赋值命令出现在方法中的任何位置,Python 默认会g_c
在局部变量中查找名称。即使在实际分配之前发生引用也是如此,这将导致经典错误:
UnboundLocalError: local variable 'g_c' referenced before assignment
现在,如果声明global g_c
出现在方法中的任何位置,即使在任何引用或赋值之后,Python 也会默认g_c
在全局变量中查找名称。但是,如果您感觉实验性的并将声明放在引用之后,您将收到警告:
SyntaxWarning: name 'g_c' is used prior to global declaration
如果你仔细想想,Python 中全局声明的工作方式显然与 Python 的正常工作方式是一致的。只是当您真正希望全局变量起作用时,规范变得烦人。
这是一个总结我刚才所说的代码的代码(还有一些观察):
g_c = 0
print ("Initial value of g_c: " + str(g_c))
print("Variable defined outside of method automatically global? "
+ str("g_c" in globals()))
class TestClass():
def direct_print(self):
print("Directly printing g_c without declaration or modification: "
+ str(g_c))
#Without any local reference to the name
#Python defaults to search for the variable in globals()
#This of course happens for all the module names you import
def mod_without_dec(self):
g_c = 1
#A local assignment without declaring reference to global variable
#makes Python default to access local name
print ("After mod_without_dec, local g_c=" + str(g_c))
print ("After mod_without_dec, global g_c=" + str(globals()["g_c"]))
def mod_with_late_dec(self):
g_c = 2
#Even with a late declaration, the global variable is accessed
#However, a syntax warning will be issued
global g_c
print ("After mod_with_late_dec, local g_c=" + str(g_c))
print ("After mod_with_late_dec, global g_c=" + str(globals()["g_c"]))
def mod_without_dec_error(self):
try:
print("This is g_c" + str(g_c))
except:
print("Error occured while accessing g_c")
#If you try to access g_c without declaring it global
#but within the method you also alter it at some point
#then Python will not search for the name in globals()
#!!!!!Even if the assignment command occurs later!!!!!
g_c = 3
def sound_practice(self):
global g_c
#With correct declaration within the method
#The local name g_c becomes an alias for globals()["g_c"]
g_c = 4
print("In sound_practice, the name g_c points to: " + str(g_c))
t = TestClass()
t.direct_print()
t.mod_without_dec()
t.mod_with_late_dec()
t.mod_without_dec_error()
t.sound_practice()
class flag:
## Store pseudo-global variables here
keys=False
sword=True
torch=False
## test the flag class
print('______________________')
print(flag.keys)
print(flag.sword)
print (flag.torch)
## now change the variables
flag.keys=True
flag.sword= not flag.sword
flag.torch=True
print('______________________')
print(flag.keys)
print(flag.sword)
print (flag.torch)
在类中使变量成为全局变量非常简单:
a = 0
class b():
global a
a = 10
>>> a
10