8

代码 1

x = 0

class Foo:
    print(x)
    x = 1
    print(x)

print(x)

结果 1

0
1
0

代码 2

x = 0

def foo():
    print(x)
    x = 1
    print(x)

foo()

结果 2

UnboundLocalError: local variable 'x' referenced before assignment.

为什么可以x从两个命名空间中引用对象class block
我不明白为什么Code 1不扔一个UnboundLocalError.
函数和类之间的不一致困扰着我。


更新:

多次阅读Python 文档后,我仍然无法理解范围规则。

以下是块:模块、函数体和类定义。...[跳过]...

如果名称绑定在块中,则它是该块的局部变量,除非声明为非局部变量。如果名称绑定在模块级别,则它是一个全局变量。(模块代码块的变量是局部变量和全局变量。)如果变量在代码块中使用但没有在代码块中定义,则它是自由变量。

如果名称绑定操作发生在代码块内的任何位置,则块内名称的所有使用都被视为对当前块的引用。如果在绑定之前在块中使用名称,这可能会导致错误。这个规则很微妙。Python 缺少声明,并允许名称绑定操作在代码块中的任何位置发生。代码块的局部变量可以通过扫描块的整个文本以进行名称绑定操作来确定。

4

3 回答 3

6
x = 0

class Foo:
    print(x)   # Foo.x isn't defined yet, so this is the global x
    x = 1      # This is referring to Foo.x
    print(x)   # So is this

print(x)

x = 0

def foo():
    print(x)   # Even though x is not defined yet, it's known to be local
               # because of the assignment
    x = 1      # This assignment means x is local for the whole function
    print(x)

foo()
于 2012-10-10T00:49:53.027 回答
1

为了使示例具有可比性,请不要忘记使用以下global语句

def foo():
    global x
    print(x)
    x = 1
    print(x)

这样你就不会得到UnboundLocalError.

于 2012-10-10T00:52:28.100 回答
1

类块不知道“局部”变量,只知道类变量。它们与局部变量的不同之处在于它们在块执行后不会被遗忘;它们将保留为类中的字段。局部变量和类变量的处理方式不仅在这方面有所不同,因此没有引发未绑定错误也就不足为奇了。毕竟你没有一个未定义的局部变量来隐藏全局变量。因此,在定义类变量之前访问全局变量是没有问题的。

也许编译器也应该以某种方式警告这一点,但目前它没有。

于 2012-10-10T00:52:56.080 回答