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

时间:2018-12-09 12:09:32

标签: python python-3.x inner-classes

如何在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 个答案:

答案 0 :(得分:1)

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

将变量设置为self.__x时,您实际上是在告诉类外的世界,只有在Outer类中进行操作时,才可以通过这种方式访问​​它。如果您尝试在外部访问,可以说在obj的定义后面加上以下print(obj.__x),您将看到相同的问题。

名称处理意味着在访问类范围之外的变量时,应调用变量_ClassName__variableName,因此,在我们的示例中,应使用print(obj._Outer__x)来{ {1}}变量。

由于您的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

然后,obj = Outer() obj._Outer__x = 10 obj.show() 的输出将始终为show(),因为您对变量所做的更改是对没有传递给x: 20的实例进行的。 / p>

如果这不是您要针对的行为,请将此行更改为:

Inner

因此,现在您可以有效地将实例化的对象传递给self.i1 = self.Inner(self)

答案 1 :(得分:0)

问题是您在self.i1 = self.Inner(Outer)中传递了该类而不是实例,并且self.__str实例< / strong>属性。

还有另一个问题。您正在使用受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 _
    
        ...