Skip to content

Instantly share code, notes, and snippets.

@isaiah
Created June 3, 2016 10:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save isaiah/2d5c93a6753119294748dc540bf83804 to your computer and use it in GitHub Desktop.
Save isaiah/2d5c93a6753119294748dc540bf83804 to your computer and use it in GitHub Desktop.
Question regarding __class__ closure

According to http://bugs.python.org/msg176429 from http://bugs.python.org/issue12370:

class C(A, B, metaclass=meta):
    def f(self):
        return __class__

To be compiled approximately like this:

def _outer_C(*__args__, **__kw__):
    class _inner_C(*__args__, **__kw__):
        def f(self):
            return __class__
    __class__ = _inner_C
    return _inner_C
C = _outer_C(A, B, metaclass=meta)

My question is:

class A:
    def foo(a):
        class X:
            x = __class__
            def fun(self):
                print(__class__)

        return X
print(A().foo().x)

Why does this work? While the following doesn't?

def bar():
    class Y:
        def fun(a):
            class X:
                m = n
                def foo(a):
                    print(a.m)
            n = 1
            return X
    n = 0
    return Y
 
if __name__ == '__main__':
  y = bar()
  x = y().fun()
  x().foo()

If the free variable is assigned in the outscope, it's turned to a cell var, and because it's assigned after the class body is evaluated, NameError is raised.

If the __class__ closure trick is really what it said to be, it should also raise a NameError, what's the trick use to make it work?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment