外部 class 如何从其内部 class 访问数据?

How can an outer class access data from its inner class?

我试图更好地理解如何使用基于 this question/answer 的非常简单的测试用例来使用子 classes。

class Outer():

    def __init__(self, x):
        self.x = super(Inner, self).__init__
        # self.x = Inner(**kwargs)

    def add_two(self):
        """ """
        return self.x + 2

    class Inner():

        def __init__(self, x=2):
            self.x = x

res = Outer(x=3).add_two()
# res = Outer({'x' : 3}).add_two()
print(res)
>> NameError: name 'Inner' is not defined

如果我 运行 相同的代码,但使 Inner() 成为自己独立的 class(与 Outer() 的子 class 相对,我收到以下错误。

TypeError: super(type, obj): obj must be an instance or subtype of type

此错误的原因是什么,我该如何解决?

在Python(或其他语言)中嵌套classes 很少有意义。在这种情况下,它根本没有任何用处。

如果在 "Outer" class 上你想要一个 "Inner" 的关联实例,那应该作为实例属性创建,在 __init__ 方法上外部 - 像这样:

class Outer():

    def __init__(self, x):
        self.x = Inner(x)
        # self.x = Inner(**kwargs)

    def add_two(self):
        """ """
        return self.x + 2


class Inner():

    def __init__(self, x=2):
        self.x = x

现在,逐步查看您的原始代码,并尝试更好地理解为什么它不起作用: 在 Python 中,在 class 的主体中声明的所有内容都成为 class 的属性 - 它的单个副本将(通常)由 class 的所有实例共享.声明一个整体 class 嵌套在句法上是合法的,但对你没有任何好处:内部 class 在任何意义上都不是来自外部世界的 "hidden" 语言:不是语言,也不是Python 开发人员通常遵循的约定。

如果您希望用户(即其他程序员,或您自己在使用此文件的代码中)创建 "Outer" 的实例并避免创建 "Inner" 的实例,只需在其前缀带有 _ 的名称。这是 Python 代码中的约定,开发人员通常会知道他们不应该相信任何 class、函数或以单个 _ 开头的其他名称可以安全地用于第 3 方代码 - 这是最接近 Python 的 "private" 或 "protected" 成员。

现在开始:

    ...
    self.x = super(Inner, self).__init__

这又没有意义。 super 或显式引用 superclass 是为了调用 superclasses - 即,您继承的 classes。您在代码中没有创建继承关系,而是创建了一种组合关系。这就是您收到该错误消息的原因 - 如果您使用的是 super 的显式版本,则您传递的对象必须是您调用 super 的 class 的子 class。这里不是这种情况。 (此外,以这种形式进行,它不调用方法 - 只是引用它 - 所有函数或方法调用都是通过使用 ()

您还可以使 Outer 继承自 Inner - 在这种情况下,Outer 将 "be" 成为一个 Inner,无需在属性中保留对它的引用 - self 将意味着两个 Outer和一个内部 class。 在这种情况下,我们在解析"Outer"的声明时需要引用"Inner",所以需要先定义:

class _Inner():

    def __init__(self, x=2):
        self.x = x

class Outer(_Inner):

    def __init__(self, x):
        super().__init__(x)

    def add_two(self):
        """ """
        return self.x + 2

注意无参数的使用super——对Python的主要改动之一 3.如果你需要写的代码仍然兼容Python 2,将参数改为super即可是明确的,调用将是 super(Outer, self).__init__().

(同样,调用它 _Inner 将意味着您的 class 的用户不应该从 _Inner 继承或实例化,而应该使用 Outer - 这是一个编码风格的约定而不是语言语法)