我正在尝试理解python2.7中名称空间的嵌套。
考虑以下不起作用的代码:
class c(object):
def debug(self):
print globals(),locals()
print x,y
class a(object):
x=7
def __init__(self):
self.y=9
class b(object):
def debug(self):
print globals(),locals()
print x,y
class d(c):
pass
如何从调用中访问变量x和y?
a().b().debug()
a.b().debug()
a().d().debug()
a.d().debug()
他们似乎都看不见x和y。
经过讨论,似乎只有显式扩展嵌套类的信息才能达到我想要的结果(避免引用全局)。例如
class a(object):
#
@classmethod
def _initClass(cls):
for v in dir(cls):
if type(cls.__dict__[v])==type:
setattr(cls.__dict__[v],'vader',cls)
#
x=7
class b(object):
def debug(self):
print b.vader.x
class d(c):
pass
a._initClass()
而且,就像a().d().debug序列中所期望的那样,即使这种技术对于访问实例变量似乎也不有用。
发布于 2014-10-23 08:51:28
Martijn已经给出了一个很好的答案,但我要尝试一下我自己的答案。
正如Martijn所说,类声明在第一次导入模块时,执行起来就像一次性函数一样,具有自己的本地作用域。在执行了类声明中的所有内容之后,这个本地范围中剩下的内容将被用作类的字典。因此,x
、__init__
、b
和d
最终都是a
类对象的属性。您的类b
和d
也是如此;它们的主体在导入模块时执行,剩下的本地作用域也用作字典。
您的代码不能工作的原因是,当debug
方法执行时,它唯一知道的作用域是全局作用域和它自己的本地作用域。在python中,方法不隐式地将类实例的字典作为其作用域的一部分,就像在C++这样的语言中所做的那样。类实例可以显式地作为self
参数出现在参数列表中(因此,python的禅“显式优于隐式”--在python中尝试import this
)。
而且,在访问和实例化其他类a
和a
上的d
之前,是否实例化a
并不重要,因为b
和d
都是a
上的类属性。因此,python可以从b
实例或直接引用a
类对象成功地检索a
和a
。
发布于 2014-10-23 08:27:36
class
对象不创建作用域;类主体只执行一次并被丢弃,生成类属性的本地命名空间。类主体从不参与嵌套作用域;它们在解析非本地名称时完全被忽略。
因此,您的x = 7
不是嵌套的b
类(或其方法)可以访问的名称。相反,它是a
上的一个类属性。访问a.x
将有效。y
是一个实例属性,您必须有一个对实例的引用,才能在任何其他地方访问它。
注意,这也适用于class b
;它现在是a
上的一个类属性,就像x
是一个类属性一样。
除了如何引用类对象之外,类b
没有什么特别之处。仅仅因为您创建了a
实例,并不意味着b
对它有任何特权访问;a().b()
不会在实例之间创建关系。你可以这样做:
b = a.b
b_instance = b()
也不会有什么区别。你甚至可以:
a.b.a = a
a.b.a()
世界也不会崩溃!(想象一下)。
https://stackoverflow.com/questions/26532730
复制