问题:嵌套类的范围?
我试图了解Python嵌套类中的作用域。这是我的示例代码:
class OuterClass:
outer_var = 1
class InnerClass:
inner_var = outer_var
类的创建未完成,并且出现错误:
<type 'exceptions.NameError'>: name 'outer_var' is not defined
尝试inner_var = Outerclass.outer_var
不起作用。我得到:
<type 'exceptions.NameError'>: name 'OuterClass' is not defined
我正在尝试从访问静态outer_var
信息InnerClass
。
有没有办法做到这一点?
I’m trying to understand scope in nested classes in Python. Here is my example code:
class OuterClass:
outer_var = 1
class InnerClass:
inner_var = outer_var
The creation of class does not complete and I get the error:
<type 'exceptions.NameError'>: name 'outer_var' is not defined
Trying inner_var = Outerclass.outer_var
doesn’t work.
I get:
<type 'exceptions.NameError'>: name 'OuterClass' is not defined
I am trying to access the static outer_var
from InnerClass
.
Is there a way to do this?
回答 0
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 Outer(object):
outer_var = 1
class Inner(object):
@property
def inner_var(self):
return Outer.outer_var
This isn’t quite the same as similar things work in other languages, and uses global lookup instead of scoping the access to outer_var
. (If you change what object the name Outer
is bound to, then this code will use that object the next time it is executed.)
If you instead want all Inner
objects to have a reference to an Outer
because outer_var
is really an instance attribute:
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
Note that nesting classes is somewhat uncommon in Python, and doesn’t automatically imply any sort of special relationship between the classes. You’re better off not nesting. (You can still set a class attribute on Outer
to Inner
, if you want.)
回答 1
我认为您可以做到:
class OuterClass:
outer_var = 1
class InnerClass:
pass
InnerClass.inner_var = outer_var
您遇到的问题是由于以下原因:
块是作为单元执行的一段Python程序文本。以下是块:模块,函数体和类定义。
(…)
范围定义了块中名称的可见性。
(…)
在类块中定义的名称范围仅限于该类块;它不会扩展到方法的代码块–包括生成器表达式,因为它们是使用函数范围实现的。这意味着以下操作将失败:
class A:
a = 42
b = list(a + i for i in range(10))
http://docs.python.org/reference/executionmodel.html#naming-and-binding
上面的意思是:
一个函数体是一个代码块,一个方法是一个函数,那么在类定义中存在于该函数体之外的名称将不会扩展到该函数体。
用您的情况解释一下:
类定义是一个代码块,然后在外部类定义中存在的内部类定义之外定义的名称不会扩展到内部类定义。
I think you can simply do:
class OuterClass:
outer_var = 1
class InnerClass:
pass
InnerClass.inner_var = outer_var
The problem you encountered is due to this:
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:
class A:
a = 42
b = list(a + i for i in range(10))
http://docs.python.org/reference/executionmodel.html#naming-and-binding
The above means:
a function body is a code block and a method is a function, then names defined out of the function body present in a class definition do not extend to the function body.
Paraphrasing this for your case:
a class definition is a code block, then names defined out of the inner class definition present in an outer class definition do not extend to the inner class definition.
回答 2
如果您不使用嵌套类,则可能会更好。如果必须嵌套,请尝试以下操作:
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
根据需要。)
You might be better off if you just don’t use nested classes. If you must nest, try this:
x = 1
class OuterClass:
outer_var = x
class InnerClass:
inner_var = x
Or declare both classes before nesting them:
class OuterClass:
outer_var = 1
class InnerClass:
inner_var = OuterClass.outer_var
OuterClass.InnerClass = InnerClass
(After this you can del InnerClass
if you need to.)
回答 3
最简单的解决方案:
class OuterClass:
outer_var = 1
class InnerClass:
def __init__(self):
self.inner_var = OuterClass.outer_var
它要求您保持明确,但不需要花费很多精力。
Easiest solution:
class OuterClass:
outer_var = 1
class InnerClass:
def __init__(self):
self.inner_var = OuterClass.outer_var
It requires you to be explicit, but doesn’t take much effort.
回答 4
在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)
In Python mutable objects are passed as reference, so you can pass a reference of the outer class to the inner class.
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)
回答 5
所有说明都可以在Python文档中找到。
对于您的第一个错误<type 'exceptions.NameError'>: name 'outer_var' is not defined
。解释是:
没有从方法内部引用数据属性(或其他方法!)的捷径。我发现这实际上提高了方法的可读性:浏览方法时,不会混淆局部变量和实例变量。
引自《 Python教程9.4》
对于第二个错误 <type 'exceptions.NameError'>: name 'OuterClass' is not defined
当正常保留类定义时(通过结尾),将创建一个类对象。
引自Python教程9.3.1
因此,当您尝试时inner_var = Outerclass.outer_var
,Quterclass
尚未创建,这就是为什么name 'OuterClass' is not defined
有关第一个错误的更详细但乏味的解释:
尽管类可以访问封闭函数的作用域,但是它们不能充当嵌套在类内的代码的封闭作用域:Python在封闭函数中搜索引用的名称,但从不搜索任何封闭类。也就是说,一个类是一个局部作用域,可以访问封闭的局部作用域,但不能用作进一步嵌套代码的封闭的局部作用域。
引用自Learning.Python(5th).Mark.Lutz
All explanations can be found in Python Documentation The Python Tutorial
For your first error <type 'exceptions.NameError'>: name 'outer_var' is not defined
. The explanation is:
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.
quoted from The Python Tutorial 9.4
For your second error <type 'exceptions.NameError'>: name 'OuterClass' is not defined
When a class definition is left normally (via the end), a class object is created.
quoted from The Python Tutorial 9.3.1
So when you try inner_var = Outerclass.outer_var
, the Quterclass
hasn’t been created yet, that’s why name 'OuterClass' is not defined
A more detailed but tedious explanation for your first error:
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.
quoted from Learning.Python(5th).Mark.Lutz