如何从 Python 中的内部 class 访问外部 class 成员?

How to access outer class member from an inner class in Python?

如何从 Python 3 中的内部 class 访问外部 class 成员?

下面是我的代码片段。

class Outer:    
    def __init__(self):
        self.__x = 20
        self.__str = "Outer Class"

    def show(self):
        self.i1 = self.Inner(Outer())
        self.i1.display()

    def fn(self):
        print("Hello from fn() of Outer Class")
        print("str : ", self.__str)

    class Inner:
        def __init__(self, outer):
            self.__str_in = "Inner Class"
            self.outer = outer

        def display(self):
            print("str_in : ", self.__str_in)
            print("Inside display() of Inner Class")
            # print("x : ", self.outer.__x)
            # print("str : ", self.outer.__str)
            # self.outer.fn()


obj = Outer()
obj.show()

如果我执行注释行,它会抛出一条错误消息 -

line 23, in display
    print("x : ", self.outer.__x)
AttributeError: type object 'Outer' has no attribute '_Inner__x'

有人可以帮忙吗?提前致谢。

问题是您传递的是 class 而不是 self.i1 = self.Inner(Outer) 中的实例,并且self.__str 是一个 实例 属性。

还有一个问题。您正在使用受 约束的 __ 前缀,因此请尽量避免这种情况。

您有 2 种方法可以解决此问题:

  • 传实例,即self.i1 = self.Inner(self)

  • 使 _str 成为 class 属性:

    class Outer:
        _str = "Outer Class"  # NOTE THE SINGLE _
    
        def __init__(self):
            self._x = 20 # NOTE THE SINGLE _
    
        ...           
    

你的代码的问题是你没有正确理解 name mangling 的含义,这正是你在变量名中添加双前导分数时所做的。

将变量设置为 self.__x 时,您实际上是在告诉 class 外部的世界,只有在 Outer 内部操作时才能以这种方式访问​​它] class。如果您尝试访问外部,假设在 obj 的定义之后添加下面的 print(obj.__x),您将看到同样的问题。

name mangling 的意思是当访问你的 class 范围之外的变量时,你应该调用变量 _ClassName__variableName,所以,在我们的例子中,你应该使用 print(obj._Outer__x) 能够 print 变量。

由于您的 Inner class 以相同的方式工作,作为外部范围,最简单的解决方案是这样重写您的 display 方法:

def display(self):
    print("str_in : ", self.__str_in)
    print("Inside display() of Inner Class")
    print("x : ", self.outer._Outer__x)
    print("str : ", self.outer._Outer__str)
    self.outer.fn()

现在,我注意到的另一件事是调用 self.i1 = self.Inner(Outer()),如果您不自觉地这样做可能会产生问题。在这里,您没有使用实例化为 obj 的相同对象数据,而是创建了 Outer 的新实例并将其发送到 Inner.
这有什么问题? 假设您添加了以下行:

obj = Outer()
obj._Outer__x = 10
obj.show()

然后你的 show() 的输出将永远是 x: 20,因为你在变量中所做的这个改变是针对一个没有传递给 Inner 的实例.

如果这不是您想要的行为,只需将此行更改为:

self.i1 = self.Inner(self)

所以现在您有效地将实例化对象传递给 Inner