如何从 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
如何从 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