<p>从OP下的讨论可以看出,这里有两件事</p>
< P> <强>第一< /强>,在Python中,没有默认对象或类作用域,如C++中的隐式^ {< CD1>}。因此,在函数内部,您的作用域就是该函数,并且您没有对类上对象上定义的变量的“自由”名称访问权。这就是我们必须传递<code>self</code>的原因——我们需要显式包含对象(和类)的环境。这意味着如果我们有</p>
<pre><code>class A:
n = 5
</code></pre>
<p>我们只能在类级别定义中访问<code>n</code>,或者通过显式保存环境:</p>
<pre><code>class A:
n = 5
a = range(n) # legal, evaluated in the class definition, where 'A' is defined and 'n' is part of the statement.
def f():
x = self.n # legal. As long you do not override self.n same as next
x = A.n # legal, this is the class variable scope
x = n # Error - we do not have 'n' for free. Even worse, if 'n' is a global variable, we are using that.
</code></pre>
<p><strong>第二个</strong>,在Python3中,与Python2不同的是,列表理解被限定了范围。不再泄漏变量,并且<code>class</code>语句的主体实际上不是一个作用域(而是一个名称空间的定义),因此也不是定义实现理解的匿名函数的作用域。所以</p>
<pre><code>class A:
n = 5
x = [n/a for a in range(n)]
</code></pre>
<p>可能被视为</p>
<pre><code>class A:
n = 5
def _anonymous_function(param):
return [n/a for a in range(param)]
x = _anonymous_function(n)
</code></pre>
<p>通过这种方式,也许可以更清楚地解释为什么<code>n</code>在一个地方合法,而在另一个地方不合法。在<code>range(n)</code>中,与答案中第二个代码段中的第一个示例类似,我们仍然在类名称空间定义语句中,并“参见”<code>n</code>。另一方面,在理解体中,我们处于一个作用域(匿名)环境中,没有看到<code>n</code>,因为它不在外部(全局)作用域中,因为<code>A</code>是一个命名空间定义。这就是它在这里中断的原因,与另一个示例相反。在Python2中,这是可行的</p>