On Fri, Jan 15, 2021 at 4:45 PM Greg Ewing <greg.ewing@canterbury.ac.nz> wrote:
On 16/01/21 9:38 am, Guido van Rossum wrote:
> On Fri, Jan 15, 2021 at 10:53 AM Larry Hastings <larry@hastings.org
> <mailto:larry@hastings.org>> wrote:
>
>         class OuterCls:
>              class InnerCls:
>                  def method(a:OuterCls.InnerCls=None): pass
>
>     We've turned the local reference into a global reference, and we
>     already know globals work fine.

[Above was what Larry wrote, the rest is me. I guess Greg's mailer is having trouble with the GMail-style quoting. :-( ]

> I think this is going too far. A static method defined in InnerCls does
> not see InnerCls (even after the class definitions are complete). E.g.
> ```
> class Outer:
>      class Inner:
>          @staticmethod
>          def foo(): return Inner
> ```
> If you then call Outer.Inner.foo() you get "NameError: name 'Inner' is
> not defined".

[Greg]
I'm not so sure about that. Conceptually, annotations are evaluated
in the environment existing when the class scope is being constructed.
The fact that we're moving them into a closure is an implementation
detail that I don't think should be exposed.

Yeah, that wasn't very clear, and I'm not 100% sure I got it right. But consider this:
```
class Outer:
    foo = 1
    class Inner:
        print(foo)
```
This gives "NameError: name 'foo' is not defined". And here there is no forward reference involved, and foo lives in the exactly the same scope/namespace as Inner.

The reason for the NameError is that class scopes don't participate in the closure game (an intentional design quirk to avoid methods referencing unqualified class variables).

So I still think that Larry's example shouldn't (have to) work.

(I agree with Greg on the 'zebra' example.)

--
--Guido van Rossum (python.org/~guido)