【问题标题】:How can I access global variable inside class in Python如何在 Python 中访问类内的全局变量
【发布时间】:2012-06-04 13:55:13
【问题描述】:

我有这个:

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 声明为 Class 变量,然后使用 print(t.g_c)
  • @agcala:Marcin 已经说过了。
  • @agcala 很可能(不确定)OP 在这里展示了一个玩具示例来证明他的问题,而其他原因导致他使用global

标签: python scope global


【解决方案1】:

通过在访问它的函数中声明global

g_c = 0

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

Python documentation 这么说,关于global 声明:

全局语句是一个适用于整个当前代码块的声明。

【讨论】:

  • g_c = 0 不必站在函数前面。也可以在函数之后创建,函数还是会知道的,不会出现“赋值前引用”的错误。
【解决方案2】:

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

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

该语句告诉 Python 编译器对该名称的任何分配(和other binding actions)都将更改全局命名空间中的值;默认设置是将分配给函数中任何位置的任何名称放在本地命名空间中。该声明仅适用于当前范围。

由于您从未在类主体中分配g_c,因此将语句放在那里没有任何效果。 global 语句只适用于它所使用的范围,从不适用于任何嵌套范围。查看global statement documentation,打开方式为:

全局语句是一个适用于整个当前代码块的声明。

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

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

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 命名空间。

【讨论】:

  • 我猜你们还在用 Python 2.7 编程,不是吗?根本不需要声明任何全局变量。看我的回答。
  • @agcala: 可能是这样,但是global 语句,如果使用,不会进入课堂,这就是答案的重点。
  • @agcala:我也不确定您所说的 Python 2.7 评论指的是什么。这里唯一特定于 Python 2 的是 print 语句。
【解决方案3】:

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

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

  1. 将键 "g_c" 输入到内置函数 globals() 可访问的字典中的前提条件。但是,在为其分配值之前,该键不会出现在字典中。

  2. (可能)改变 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 的正常工作方式相一致。只是当您真正希望全局变量起作用时,规范变得烦人。

这里是总结了我刚才所说的代码(还有一些观察):

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()

【讨论】:

  • 还有一点需要注意:虽然被多处理的函数仍然无法访问通用全局变量,但回调函数可以。
【解决方案4】:
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)

【讨论】:

    【解决方案5】:

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

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

    【讨论】:

    • 简单但在这种情况下是不必要的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-12
    • 1970-01-01
    • 2010-09-22
    • 2016-08-24
    相关资源
    最近更新 更多