Nested classes' scope?
我试图理解Python中嵌套类的范围。下面是我的示例代码:
1 2 3 4 | class OuterClass: outer_var = 1 class InnerClass: inner_var = outer_var |
类的创建没有完成,我得到错误:
1 | <type 'exceptions.NameError'>: name 'outer_var' is not defined |
尝试
1 | <type 'exceptions.NameError'>: name 'OuterClass' is not defined |
我试图从
有办法吗?
1 2 3 4 5 6 7 | class Outer(object): outer_var = 1 class Inner(object): @property def inner_var(self): return Outer.outer_var |
这与其他语言中的类似操作不同,它使用全局查找而不是限定对
如果您希望所有
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 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中有点不常见,并且不会自动暗示类之间的任何特殊关系。你最好不要筑巢。(如果需要,还可以将
我认为你可以简单地做到:
1 2 3 4 5 6 | class OuterClass: outer_var = 1 class InnerClass: pass InnerClass.inner_var = outer_var |
您遇到的问题是由以下原因造成的:
A block is a piece of Python program text that is executed as a unit.
The following are blocks: a module, a function body, and a class
definition.
(...)
A scope defines the visibility of a name within
a block.
(...)
The scope of names defined in a class block is
limited to the class block; it does not extend to the code blocks of
methods – this includes generator expressions since they are
implemented using a function scope. This means that the following will
fail:
1
2
3
4
5 class A:
a = 42
b = list(a + i for i in range(10))http://docs.python.org/reference/executionmodel.html#naming-and-binding
以上是指:函数体是一个代码块,方法是一个函数,那么在类定义中存在的函数体之外定义的名称不会扩展到函数体。
为您的案例解释如下:类定义是代码块,那么在外部类定义中存在的内部类定义之外定义的名称不会扩展到内部类定义。
如果不使用嵌套类,可能会更好。如果必须嵌套,请尝试以下操作:
1 2 3 4 5 | x = 1 class OuterClass: outer_var = x class InnerClass: inner_var = x |
或者在嵌套这两个类之前声明它们:
1 2 3 4 5 6 7 | class OuterClass: outer_var = 1 class InnerClass: inner_var = OuterClass.outer_var OuterClass.InnerClass = InnerClass |
(在这之后,如果需要的话,您可以使用cx1〔7〕。)
最简单的解决方案:
1 2 3 4 5 | class OuterClass: outer_var = 1 class InnerClass: def __init__(self): self.inner_var = OuterClass.outer_var |
它要求你明确,但不需要太多的努力。
在Python中,可变对象作为引用传递,因此可以将外部类的引用传递给内部类。
1 2 3 4 5 6 7 8 9 10 11 | 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文档中找到python教程
你的第一个错误是
There is no shorthand for referencing data attributes (or other methods!) from within methods. I find that this actually increases the readability of methods: there is no chance of confusing local variables and instance variables when glancing through a method.
引自Python教程9.4
第二个错误是
When a class definition is left normally (via the end), a class object is created.
引自Python教程9.3.1
所以当你尝试
对您的第一个错误的更详细但乏味的解释是:
Although classes have access to enclosing functions’ scopes, though, they do not act
as enclosing scopes to code nested within the class: Python searches enclosing functions
for referenced names, but never any enclosing classes. That is, a class is a local scope
and has access to enclosing local scopes, but it does not serve as an enclosing local scope
to further nested code.
引自learning.python(5).mark.lutz