我正在尝试理解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
。
有办法做到这一点吗?
答案 0 :(得分:103)
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
。)
答案 1 :(得分:43)
我认为你可以做到:
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
以上表示:
函数体是代码块,方法是函数,那么在类定义中存在的函数体定义的名称不会扩展到函数体。
根据你的情况解释这个:
类定义是一个代码块,然后在外部类定义中出现的内部类定义中定义的名称不会扩展到内部类定义。
答案 2 :(得分:20)
如果您不使用嵌套类,可能会更好。如果你必须筑巢,试试这个:
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
之后。)
答案 3 :(得分:4)
最简单的解决方案:
class OuterClass:
outer_var = 1
class InnerClass:
def __init__(self):
self.inner_var = OuterClass.outer_var
它要求你明确,但不需要太多努力。
答案 4 :(得分:1)
在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)
答案 5 :(得分:0)
所有解释都可以在 Python文档Python教程
中找到首次出现错误<type 'exceptions.NameError'>: name 'outer_var' is not defined
。解释是:
没有从方法中引用数据属性(或其他方法!)的简写。我发现这实际上增加了方法的可读性:在浏览方法时,没有可能混淆局部变量和实例变量。
引自 Python教程9.4
对于您的第二个错误<type 'exceptions.NameError'>: name 'OuterClass' is not defined
当正常保留类定义(通过结尾)时,会创建一个类对象。
引用自
因此,当您尝试inner_var = Outerclass.outer_var
时,Quterclass
尚未创建,这就是为什么name 'OuterClass' is not defined
对您的第一个错误进行更详细但乏味的解释:
虽然类可以访问封闭函数的作用域,但它们不起作用 作为嵌套在类中的代码的封闭范围:Python搜索封闭的函数 对于引用的名称,但从不包含任何封闭的类。也就是说,类是本地范围 并且可以访问封闭的本地范围,但它不能作为封闭的本地范围 进一步嵌套代码。
引用 Learning.Python(5th).Mark.Lutz