如何以类似于访问全局变量的方式访问OuterClass
变量?
例如:
global_variable = 'global_variable'
class InnerClass:
def __init__(self):
pass
def test(self):
return super().variable
def test_global(self):
return global_variable
class OuterClass:
def __init__(self, inner_class_instance):
self.variable = 'class_variable'
self.inner_class_instance = inner_class_instance
运行以下命令将返回全局变量:
inner = InnerClass()
outer = OuterClass(inner)
outer.inner_class_instance.test_global()
但是,尝试访问nonlocal
类变量会导致AttributeError
:
outer.inner_class_instance.test()
super()
在InnerClass.test
中使用不正确,因为OuterClass
不是InnerClass
的基类。如何以与访问全局变量类似的方式访问OuterClass
变量?但这没有将上下文参数传递给InnerClass
。在nonlocal variable
中使用InnerClass.test
会产生SyntaxError
。
此外,如何以及为什么从InnerClass.test
访问全局变量?
答案 0 :(得分:1)
在test(self)
的{{1}}方法中,您错误地理解了表达式InnerClass
的含义。 super().variable
在这里是指super()
的超类,尽管它在代码中没有明确说明,但恰好是称为InnerClass
的预定义类。并且Object
类当然没有名为Object
的属性。这就是为什么该行引发错误
“超级”对象没有属性“变量”
您的另一个问题是“如何访问variable
变量?”。
我想先在这里整理一下概念的一些基本方面。
首先,您在OuterClass
中拥有的名称为InnerClass
的东西实际上是variable
的属性。因此,我宁愿将您的问题重新表述为“如何通过InnerClass
的方法访问OuterClass
属性?”。
第二,仅仅因为InnerClass
的{{1}}方法执行时OuterClass
收到了对InnerClass
实例的引用,并不意味着__init__()
绝对是“外部”或“周围” OuterClass
。
从OuterClass
中的代码的角度来看,InnerClass
只是另一个类,没有特殊的地位-它既不是超类(祖先类),也不是外部类(周围的阶级)。因此,要从称为InnerClass
的{{1}}方法内部访问OuterClass
实例的属性,首先需要一个名称,该名称包含对OuterClass
实例的引用。因此,例如,在InnerClass
方法中,如果您碰巧有一个名为test()
的名称,该名称包含对OuterClass
实例的引用,则可以肯定地引用{{1 }}属性称为test()
,使用my_outer_inst
。
答案 1 :(得分:0)
从第一个问题开始,在OuterClass
的代码中还有更多要定义的内容。 OuterClass
说 variable
,这表示它不是在类内部定义的。
尝试执行此操作,my_outer_inst.variable
。您再次得到相同的variable
。定义/声明AttributeError
,然后尝试一次。
第二个问题,''super' object has no attribute 'variable''
变量是在类外部声明的变量。可以在任何地方访问它们。但是,为了更改其值,必须在类内部将其声明为inner.test()
。
答案 2 :(得分:0)
被分配为其他实例的属性的实例通常无法获得对包含实例的引用。一方面,此类引用可能为零或不止一个!例如,如果您使用相同的OuterClass
实例创建了InnerClass
的第二个实例,则可能要读取两个可能不同的variable
属性。
通常,如果要访问对象的属性,则需要首先引用该对象。除非您安排一些替代的API,否则仅对您的引用是不够的。
例如,也许InnerClass
希望在其OuterClass
方法中获得对test
的引用,而OuterClass
得到一种方法来传递自身:
class InnerClass:
def test(self, outer):
return outer.variable
class OuterClass:
def __init__(self, inner, variable):
self.inner = inner
self.variable = variable
def run_test(self):
return self.inner.test(self)
out = OuterClass(InnerClass(), "foo")
print(out.run_test())
您还可以让您的类设置循环引用,它们之间互相引用。然后,任何一个都可以与另一个做些事情:
class InnerClass:
def __init__(self):
self.outer = None
def test(self):
if self.outer is None:
raise ValueError("Not in an OuterClass instance!")
return self.outer.variable
class OuterClass:
def __init__(self, inner, variable):
self.inner = inner
inner.outer = self # set reference back to us!
self.variable = variable
out = OuterClass(InnerClass(), "foo")
print(out.inner.test())
这是这种方法的非常粗糙的版本,您可能想要确保引用保持一致(例如,防止两个不同的InnerClass
实例使用同一OuterClass
实例)。
请注意,像这样的循环引用使垃圾收集器的工作更加困难。通常,Python对象的最后一个引用消失后会立即清除它们。但是具有引用循环的对象之间始终总是存在引用之间的引用,因此GC需要检查整个对象集是否全部都消失了。对于一个仅包含两个对象的循环,如本例所示,它可能会很好地管理它,但是在更大的数据结构中,它可能会更棘手。