Why doesn't "class" start a new scope like "def" does?
<p>I'm not entirely sure this is for stackoverflow, so please correct me if not.</p>

<p>i.e. say we have t.py with contents:
</p>

<pre><code>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)
</code></pre>

<p>And now we execute it: <code>$ python3 t.py</code></p>

<pre><code>A: &lt;class '__main__.A'&gt;
From B: A: &lt;class '__main__.A'&gt;
AA: &lt;class '__main__.AA'&gt;
From BB: AA:
Traceback (most recent call last):
  File "t.py", line 9, in &lt;module&gt;
    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
</code></pre>

<p>From the docs:</p>

<blockquote>
  <p>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.</p>
</blockquote>

<p>So I understand the behaviour but not the rationale behind making the scope not be lexical like everywhere else. It goes against "Special cases aren't special enough to break the rules." Why does <code>class</code> behave differently than, say, <code>def</code>?</p>

<p>Is this a "practicality beats purity" case? If so, what's the justification? I initially thought it might be an artefact of python 2.x, but as you can see above, the behaviour is also present in python 3.3.</p>
