3

我在 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 使用什么规则来处理其奇怪的作用域?

4

2 回答 2

5

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

于 2012-07-25T09:00:07.213 回答
4

基本上,有两个规则:

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

但是,您可以更改 #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
于 2012-07-25T09:13:38.110 回答