如何在 Python 中的 class 中创建嵌套 class 的实例?

How do I create an instance of a nested class from within that class in Python?

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


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

ExampleClass().Example()

当我运行上面的代码时,我得到了异常:name 'NestedClass' is not defined

是否有其他方法可以使用嵌套 class 或我做错了什么?

理想情况下,如果创建新实例,您希望使用 class 方法,这是您如何操作的示例:

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

或者,如果您想使用当前实例创建一个实例(例如,如果您需要传递一些参数),那么您可以通过使用 type(self)self.__class__.

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

虽然不知道您的用例,但这可能不是您想要的。

您的错误来自 python 处理 classes 的方式。

当遇到class语句时,class的主体是运行,它定义的名字放在单独的命名空间中,最终会成为class __dict__。 class 对象不会被创建并绑定到它的名字,直到(很好)在主体有 运行 之后。这意味着当你把 class NestedClass: 放在 class ExampleClass: 的主体中时,ExampleClass 还不存在,NestedClass 也不存在。间接地,因此,所有新的 class 命名空间都位于可用的顶级命名空间(例如全局或函数)中,并且实际上并未相互嵌套。

作为这种操作顺序的结果,class 主体根本不知道周围 classes 的名称空间。因此 NestedClass 的命名空间会查看全局命名空间,而不是 ExampleClass__dict__,正如您可能期望来自 Java 的命名空间。在函数中定义的 class 将能够在全局变量之前看到函数局部命名空间,但仍然不能看到封闭的 class.

因此,行 newclass = NestedClass() 引发了一个错误。函数名称空间或全局名称空间中不存在名称 NestedClass。提供三种简单的解决方法:

  1. 使用静态范围__class__:

    newclass = __class__()
    
  2. 通过全局名称引用 class:

    newclass = ExampleClass.NestedClass()
    
  3. 不要在 Python 中使用嵌套的 classes。这通常是首选方法。只需将 NestedClass 移动到顶层即可。然后你的 makenew 方法无需修改就可以工作,并且 ExampleClass.Example 可以直接引用 NestedClass 而不是 self.NestedClass.