Python如何处理全局变量?

时间:2012-07-25 08:58:15

标签: python

我在Python中遇到了一些奇怪的全局变量处理。我希望有人可以解释并证明这些惊喜!

A)此代码按预期打印10:

def func():
  print(a)
a = 10
func()

B)此代码引发了一个过早引用的例外:

def func():
  print(a)
  a += 1
a = 10
func()

C)但是这段代码按预期打印[10]:

def func():
  print(a)
  a.append(1)
a = [10]
func()

所以我可以收集a的类型更改其范围,此外后来甚至尚未达到的语句会改变a的显示方式。我知道我可以在函数的开头使用global a,但它相当冗长。

有人能告诉我Python正在使用哪些规则来处理其奇怪的范围?

2 个答案:

答案 0 :(得分:5)

第二个实例重新绑定 a,因此编译器会为其生成本地访问权限。另外两个只读a,因此执行正常的全局范围搜索。

答案 1 :(得分:4)

基本上,有两条规则:

  1. 当你只读取一个变量(在一个范围内)时,Python将沿着范围链向上移动,直到找到该名称的变量。
  2. 当您至少写入一次变量时,Python将始终在当前范围内创建变量。
  3. 您可以更改#2的行为,但是:

    • 如果您希望名称引用模块级变量,则可以使用global my_module_variable。当您现在写信给my_module_variable时,Python将创建一个本地变量。
    • 从Python 3开始,您还可以使用名称引用封闭范围中的变量:使用nonlocal my_non_local_variable使其引用最近的封闭范围中的变量。

    代码中的问题

    B)您正在使用+=:您正在尝试写入变量。因此规则2生效,它将写入当前范围中的变量。但是,它也必须从中读取(print(a)),但该变量还没有值,因为您之前没有写过它。 Python不允许您在函数中混合使用规则1.和规则2.

    如果您希望func()使用a = 10变量,可以像这样更改代码:

    >>>> def func()
            global a
            print(a)
            a += 1
    >>>> a = 10
    >>>> func()
    10
    >>>> func()
    11