Why doesn't “class” start a new scope like “def” does?
我不完全确定这是为了stackoverflow,所以如果不是请纠正我。
也就是说,我们有包含以下内容的T.py:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | class A(object): pass print("A:", A) class B(object): print("From B: A:", A) class OuterClass(object): class AA(object): pass print("AA:", AA) class BB(object): print("From BB: AA:", AA) |
现在我们执行:
1 2 3 4 5 6 7 8 9 10 11 12 | A: <class '__main__.A'> From B: A: <class '__main__.A'> AA: <class '__main__.AA'> From BB: AA: Traceback (most recent call last): File"t.py", line 9, in <module> class OuterClass(object): File"t.py", line 14, in OuterClass class BB(object): File"t.py", line 15, in BB print"From BB: AA:", AA NameError: name 'AA' is not defined |
来自文档:
A class definition is an executable statement. It first evaluates the
inheritance list, if present. Each item in the inheritance list should
evaluate to a class object or class type which allows subclassing. The
class’s suite is then executed in a new execution frame (see section
Naming and binding), using a newly created local namespace and the
original global namespace. (Usually, the suite contains only function
definitions.) When the class’s suite finishes execution, its execution
frame is discarded but its local namespace is saved. [4] A class
object is then created using the inheritance list for the base classes
and the saved local namespace for the attribute dictionary. The class
name is bound to this class object in the original local namespace.
因此,我理解行为,但不理解使范围不像其他地方那样具有词法意义的理由。它违背了"特殊情况不足以打破规则",为什么
这是一个"实用胜纯洁"的例子吗?如果是这样,有什么理由?我最初认为它可能是Python 2 .x的一个伪像,但正如上面所见,Python 3.3也存在这种行为。
正如Wooble在注释中指出的,类块确实创建了一个新的范围。问题是类块作用域中的名称不能被嵌套在该作用域中的作用域访问。文件中提到了这一点:
The scope of names defined in a class block is limited to the class block; it does not extend to the code blocks of methods – this includes comprehensions and generator expressions since they are implemented using a function scope.
我现在找不到它的来源,但在某个地方(我想是关于stackoverflow的问题),我找到了一个合理的理由:如果类def可以在嵌套块中访问,那么方法名将隐藏全局函数,包括内置函数。这将使创建具有短、简单名称的方法,但同时也使用相同名称的内置函数的类变得困难。例如,您不能这样做:
1 2 3 4 5 | class SomeDataStructure(object): def sum(self): return sum(self._data) def otherCalc(self): return sum(item for item in somethingElse) |
如果类块在方法内的作用域内,这将导致无限递归,因为内部
现在,这个论点实际上只对类内的函数有意义,因为函数体不是在