嵌套类的范围?
我想了解在Python中的嵌套类的范围。 这是我的示例代码:
class OuterClass: outer_var = 1 class InnerClass: inner_var = outer_var
类的创build没有完成,我得到的错误:
<type 'exceptions.NameError'>: name 'outer_var' is not defined
尝试inner_var = Outerclass.outer_var
不起作用。 我得到:
<type 'exceptions.NameError'>: name 'OuterClass' is not defined
我正在尝试从InnerClass
访问静态InnerClass
。
有没有办法做到这一点?
class Outer(object): outer_var = 1 class Inner(object): @property def inner_var(self): return Outer.outer_var
这与其他语言的类似工作并不完全相同,并且使用全局查找而不是范围访问outer_var
。 (如果你改变Outer
绑定的对象的名字,那么这个代码将在下次执行时使用该对象。)
如果您希望所有的Inner
对象都具有对Outer
的引用,因为outer_var
是一个实例属性:
class Outer(object): def __init__(self): self.outer_var = 1 def get_inner(self): return self.Inner(self) # "self.Inner" is because Inner is a class attribute of this class # "Outer.Inner" would also work, or move Inner to global scope # and then just use "Inner" class Inner(object): def __init__(self, outer): self.outer = outer @property def inner_var(self): return self.outer.outer_var
请注意,嵌套类在Python中并不常见,并不会自动暗示类之间的任何特殊关系。 你最好不要嵌套。 (如果你愿意的话,你仍然可以在Outer
到Inner
设置一个类属性。)
我想你可以简单地做:
class OuterClass: outer_var = 1 class InnerClass: pass InnerClass.inner_var = outer_var
你遇到的问题是由于这个:
块是作为一个单元执行的一段Python程序文本。 以下是块:模块,函数体和类定义。
(……)
范围定义块内名称的可见性。
(……)
类块中定义的名称范围仅限于类块; 它不会扩展到方法的代码块 – 这包括生成器expression式,因为它们是使用函数作用域实现的。 这意味着以下将失败:class A: a = 42 b = list(a + i for i in range(10))
http://docs.python.org/reference/executionmodel.html#naming-and-binding
以上意思是:
一个函数体是一个代码块,一个方法是一个函数,那么从类定义中出现的函数体中定义的名称不会扩展到函数体。
为你的情况解释这个:
一个类定义是一个代码块,那么在外部类定义中出现的内部类定义之外定义的名称不会扩展到内部类定义。
如果你不使用嵌套类,你可能会更好。 如果你必须嵌套,试试这个:
x = 1 class OuterClass: outer_var = x class InnerClass: inner_var = x
或者在嵌套它们之前声明这两个类:
class OuterClass: outer_var = 1 class InnerClass: inner_var = OuterClass.outer_var OuterClass.InnerClass = InnerClass
(在此之后,如果需要,可以del InnerClass
。)
最简单的解决scheme
class OuterClass: outer_var = 1 class InnerClass: def __init__(self): self.inner_var = OuterClass.outer_var
它要求你明确,但不需要太多的努力。
在Python中,可变对象作为引用传递,因此可以将外部类的引用传递给内部类。
class OuterClass: def __init__(self): self.outer_var = 1 self.inner_class = OuterClass.InnerClass(self) print('Inner variable in OuterClass = %d' % self.inner_class.inner_var) class InnerClass: def __init__(self, outer_class): self.outer_class = outer_class self.inner_var = 2 print('Outer variable in InnerClass = %d' % self.outer_class.outer_var)
所有的解释都可以在Python Documentation Python Tutorial中find
对于你的第一个错误<type 'exceptions.NameError'>: name 'outer_var' is not defined
。 解释是:
从方法中引用数据属性(或其他方法!)没有简写。 我发现这实际上增加了方法的可读性:当通过方法浏览时,不会混淆局部variables和实例variables。
引自“Python教程9.4”
对于你的第二个错误<type 'exceptions.NameError'>: name 'OuterClass' is not defined
当类定义保持正常(通过结束)时,创build一个类对象。
引自Python Tutorial 9.3.1
所以当你尝试inner_var = Outerclass.outer_var
, Quterclass
还没有被创build,这就是为什么name 'OuterClass' is not defined
你的第一个错误更详细但乏味的解释:
虽然类可以访问封闭函数的作用域,但是它们不能作为封装在类中的封闭作用域:Pythonsearch为引用名称封装函数,但不会包含任何封闭类。 也就是说,一个类是一个本地作用域,并且可以访问封闭的本地作用域,但是它不能作为一个封闭的本地作用域来进一步嵌套代码。
引自Learning.Python(5th).Mark.Lutz