首页 文章

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

提问于
浏览
0

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

下面是我的代码片段 .

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'

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

2 回答

  • 1

    您的代码的问题在于您没有正确理解 name mangling 的含义,'s exactly what you'在您的变量名称中添加双重领先分数时正在执行此操作 .

    将变量设置为 self.__x 时,您实际所做的就是告诉您 class 以外的世界,只有在 Outer 类内部操作时才能以这种方式访问它 . 如果你试图访问外部,让我们说 obj 定义后添加以下 print(obj.__x) ,你会看到同样的问题 .

    名称修改意味着当访问类的范围之外的变量时,应该调用变量 _ClassName__variableName ,因此,在我们的示例中,您应该使用 print(obj._Outer__x) 来能够 print 变量 .

    由于 Inner 类的工作方式相同,因此作为外部范围,最简单的解决方案是以这种方式重写 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 .
    And what's the problem with this? 假设你添加了以下几行:

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

    然后 show() 的输出将始终为 x: 20 ,因为您在变量中完成的更改是针对未传递给 Inner 的实例 .

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

    self.i1 = self.Inner(self)
    

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

  • 0

    问题是您在 self.i1 = self.Inner(Outer) 中传递 the class 而不是 an instance ,而 self.__strinstance 属性 .

    还有另一个问题 . 您正在使用 __ 前缀,该前缀受name mangling影响,因此请尽量避免这种情况 .

    你有2种方法来解决这个问题:

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

    要么

    • 使 _str 成为一个类属性:
    class Outer:
        _str = "Outer Class"  # NOTE THE SINGLE _
    
        def __init__(self):
            self._x = 20 # NOTE THE SINGLE _
    
        ...
    

相关问题