3
class ExampleClass():
    def Example(self):
        self.nestedinstance = self.NestedClass()
        self.nestedinstance.makenew()


    class NestedClass():
        def makenew(self):
            newclass = NestedClass()

ExampleClass().Example()

When I run the above code I get the exception: name 'NestedClass' is not defined

Is there a different way to do this with a nested class or have I done something wrong?

2
  • 5
    NestedClass is only accessible via the class, even in makenew you'd have to use ExampleClass.NestedClass(). You likely don't really need to nest classes. Commented Aug 24, 2021 at 15:39
  • Please post a stacktrace, because in this case it would have made it very clear where the error is coming from. Commented Aug 24, 2021 at 15:42

2 Answers 2

2

You ideally want to be using classmethods if creating a new instance, this is an example of how you'd do it:

class NestedClass():
    @classmethod
    def makenew(cls):
        newclass = cls()

Alternatively if you wanted to create an instance using the current instance (for example if you needed to pass in some arguments), then you can get the class by using type(self) or self.__class__.

class NestedClass():
    def makenew(self):
        newclass = type(self)()

Without knowing your use case though, this may not be what you're after.

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

Comments

1

Your error comes from how python handles classes.

When it encounters a class statement, the body of the class is run, and the names it defines are placed in a separate namespace, which will eventually become the class __dict__. The class object is not created and bound to its name until (well) after the body has run. That means that when you put class NestedClass: inside the body of class ExampleClass:, ExampleClass does not exist yet, and neither does NestedClass. Indirectly because of this, all the new class namespaces live in the top level available namespace (e.g. global or function), and are not actually nested within one another.

As a consequence of this order of operations, class bodies are not aware of the namespaces of surrounding classes at all. So the namespace of NestedClass looks out to the global namespace, not to the __dict__ of ExampleClass, as you might expect coming from say Java. A class defined in a function would be able to see the functions local namespace before globals, but still not that of an enclosing class.

And so, the line newclass = NestedClass() raises an error. The name NestedClass does not exist in the function's namespace, or in the global namespace. There are three simple workarounds available:

  1. Use the staticly scoped __class__:

    newclass = __class__()
    
  2. Refer to the class by its global name:

    newclass = ExampleClass.NestedClass()
    
  3. Don't use nested classes in Python. This is generally the preferred approach. Just move NestedClass to the top level. Then your makenew method will work without modification, and ExampleClass.Example can refer to NestedClass directly instead of as self.NestedClass.

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.