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使用什么规则来处理其奇怪的范围吗?

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

基本上有两个规则:

  1. 当您只读取一个变量(在作用域内)时,Python将沿着作用域链向上移动,直到找到该名称的变量
  2. 当您至少对一个变量写入一次时,Python将始终在当前作用域中创建该变量

但是,您可以更改#2的行为:

  • 如果希望名称引用模块级变量,可以使用global my_module_variable。现在写入my_module_variable时,Python将而不是创建局部变量
  • 从Python3开始,您还可以使用一个名称来引用封闭作用域中的变量:使用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

最新更新