1

I would like to achieve something similar to this construction:

class Outer:
    class A:
        foo = 1

    class B:
        def __init__(self):
            self.bar = A.foo

Outer.B().bar  # ==> 1

But this fails with

NameError: name 'A' is not defined

I'm not even sure I understand why as A is (I thought) in scope.

Could you help me clarify why this doesn't work and how I could get around it?

2
  • Nope, class scopes do not create enclosing scopes. That is why in a method you can use A, you would have to use Outer.A, as you'd have to in B.__init__. But why are you using nested classes to begin with? It's not a common pattern in Python... what advantage is it providing? Commented Dec 17, 2018 at 21:26
  • @juanpa.arrivillaga OK, I didn't realise that class scopes where different.I agree that this is not a very common pattern, and I only use it for the first time here, basically I have two very small helper classes (mainly "containers" for class attributes) and I don't think it is worth moving that to a module. Also, those two small classes are not intended to be part of the public interface. Commented Dec 18, 2018 at 12:17

4 Answers 4

2

Names are looked up only in globals, locals, and nonlocal cells (but you don't have a closure here).

Write Outer.A instead of A, or consider making Outer a module.

Sign up to request clarification or add additional context in comments.

2 Comments

Indeed, very simple, I initially thought that Outer would not be available as the class was not created yet.
Outer is not available for code executed at class scope. It is available for code executed at function scope, since the functions are only executed later. Note also that __class__ exists, but it's mainly useful for reload or copy-pasted code to prevent typos.
1

It works if you use Outer.A.foo.

Comments

1

Just like what you did for Outer.B().bar: do the same for self.bar=Outer.A().foo

Comments

1

Inner classes in Python do not have acces to the members of the enclosing class. A is not in scope of B as you state. A and B are both in scope of Outer, but they do not know of each other. Therefore a possible solution to your problem:

class Outer:
    class A:
        foo = 1

    class B:
        def __init__(self, class_a):
            self.bar = class_a.foo

    def __init__(self):
        self.a = self.A()
        self.b = self.B(self.a)


print(Outer.A.foo) # 1
print(Outer.B.bar) # AttributeError: type object 'B' has no attribute 'bar'

outer = Outer()
print(outer.a.foo)  # 1
print(outer.b.bar)  # 1

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.