如何在Python中访问类内的全局变量

如何在Python中访问类内的全局变量,python,scope,global,Python,Scope,Global,我有这个: 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的函数中声明它,从而实际修改全局变量g_c?: g_c = 0 class TestClass(): def r

我有这个:

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的函数中声明它,从而实际修改全局变量g_c?

g_c = 0

class TestClass():
    def run(self):
        global g_c
        for i in range(10):
            g_c = 1
            print(g_c)
关于
global
语句

global语句是一个声明,用于保存整个当前代码块


您需要在函数中移动
全局
声明:

class TestClass():
    def run(self):
        global g_c
        for i in range(10):
            g_c = 1
            print(g_c)
该语句告诉Python编译器,对该名称的任何赋值(和)都将改变全局名称空间中的值;默认情况下,将分配给函数中任何位置的任何名称放在本地命名空间中。该语句仅适用于当前范围

由于您从未在类主体中分配给
g_c
,因此将语句放在那里没有任何效果。
global
语句只适用于它所使用的作用域,而不适用于任何嵌套的作用域。请参见,它以以下方式打开:

global语句是一个声明,用于保存整个当前代码块

嵌套函数和类不是当前代码块的一部分

我将在此处插入禁止使用全局变量共享更改状态的强制性警告:不要这样做,这会使您更难对代码的状态进行推理,更难测试,更难重构,等等。如果您必须共享更改的单例状态(整个程序中的一个值),则至少使用类属性:


请注意,我们如何仍然可以从外部访问相同的值,名称空间为
TestClass
名称空间。

我理解,使用全局变量有时是最方便的,尤其是在使用类使最简单的事情变得更难的情况下(例如,
多处理
)。我在声明全局变量时遇到了同样的问题,并通过一些实验解决了这个问题

类中的
run
函数未更改
g_c
的原因是
g_c
中对全局名称的引用未在函数中精确建立。Python处理全局声明的方式实际上相当棘手。命令
global g_c
有两种效果:

  • 先决条件是键
    “g_c”
    进入内置函数
    globals()
    可访问的字典。但是,在为该键指定值之前,该键不会出现在字典中

  • (可能)改变Python在当前方法中查找变量
    g_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的正常工作方式是一致的。当你真的想让一个全局变量工作时,这个标准就变得很烦人了

    下面是一段代码,它总结了我刚才所说的内容(还有一些观察):


    在类中使变量成为全局变量非常简单:

    a = 0
    
    class b():
        global a
        a = 10
    
    >>> a
    10
    

    请注意,类的意义在于消除(真正的)全局状态,并在类和对象中对其进行管理。您不需要声明任何全局变量。只需将g_c声明为类变量,然后使用print(t.g_c)@agcala:这就是Marcin已经说过的。@agcala很可能(不是说肯定)OP在这里公开了一个玩具示例来演示他的问题,其他原因导致他使用
    global
    还有一件事需要注意:虽然经过多处理的函数仍然无法访问通用的全局变量,但回调函数可以。在这种情况下,回调函数很简单但不必要。我想你们仍然在用Python 2.7编程,不是吗?根本不需要声明任何全局变量。请看我的答案。@agcala:可能是这样,但是
    global
    语句(如果使用的话)不在课堂上,这就是答案的重点。@agcala:我也不确定你在说Python 2.7时指的是什么。这里唯一特定于Python 2的是
    print
    语句。
    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