类定义代码块以及传给exec()和eval()的参数的作用域是特殊情况。

类定义是可能使用并定义名称(变量)的可执行语句。 这些引用遵循正常的名称解析规则,例外之处在于未绑定的局部变量将会在全局命名空间中查找。 类定义的命名空间会成为该类的属性字典。

例如:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 变量对象a拥有全局作用域
a = "Hello"

class A:
    # 实例方法调用在类内部未绑定的变量a
    # 未绑定的变量a将会在全局命名空间中查找。值是Hello
    def print_a(self):
        print(a)

    # 实例方法调用在类内部未绑定的变量b
    # 未绑定的变量b将会在全局命名空间中查找。查找不到,抛出NameError异常
    def print_b(self):
        print(b)

    # 类方法调用在类内部未绑定的变量a
    @classmethod
    def print_a_by_class(cls):
        print(a)

aa = A()
aa.print_a()           # 输出Hello
A.print_a_by_class()   # 输出Hello
aa.print_b()           # 全局空间也没有找到变量b,抛出NameError异常

执行以上程序会输出如下结果:

1
2
3
4
5
6
7
8
Hello
Hello
Traceback (most recent call last):
  File "main.py", line 22, in <module>
    aa.print_b()
  File "main.py", line 12, in print_b
    print(b)
NameError: name 'b' is not defined

在类代码块中定义的名称的作用域会被限制在类代码块中;它不会扩展到方法的代码块中 – 这也包括推导式和生成器表达式,因为它们都是使用函数作用域实现的。

例子1

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# 变量对象a拥有全局作用域
a = "Hello"

class A:
    # 变量对象a拥有类A的作用域,但是不能在类内部的方法print_a中使用。
    a = "class var"

    # 实例方法调用在类内部绑定的变量a
    def print_a(self):
        print(a)

aa = A()
aa.print_a()           # 输出Hello,而不是class var

例子2,生成器表达式不能使用局部变量a,抛出NameError异常。

1
2
3
4
5
class A:
    a = 42
    b = list(a + i for i in range(10))

aa = A()

执行以上程序会输出如下结果:

1
2
3
4
5
6
7
8
Traceback (most recent call last):
  File "main.py", line 1, in <module>
    class A:
  File "main.py", line 3, in A
    b = list(a + i for i in range(10))
  File "main.py", line 3, in <genexpr>
    b = list(a + i for i in range(10))
NameError: name 'a' is not defined

例子3,推导式表达式不能使用局部变量a,抛出NameError异常。

1
2
3
4
5
class A:
    a = 42
    b = [a + i for i in range(10)]

aa = A()

执行以上程序会输出如下结果:

1
2
3
4
5
6
7
8
Traceback (most recent call last):
  File "main.py", line 1, in <module>
    class A:
  File "main.py", line 3, in A
    b = [a + i for i in range(10)]
  File "main.py", line 3, in <listcomp>
    b = [a + i for i in range(10)]
NameError: name 'a' is not defined

转载请注明本网址。