为什么在__init__期间实例化的对象不能看到它们的创建者?

fra*_*xel 2 python oop instantiation init

好吧,我也是SO,OOP和python的新手,所以请温柔;)

我在其他地方寻找与此范围问题相关的线索和解释,但没有发现任何问题.如有任何帮助,我将不胜感激.

示例代码:

class Zeus(object):
    def __init__(self):
        self.name='zeus'
        self.maze=Maze()
        self.maze.get_zeus_name_1()
        self.maze.get_zeus_name_2(self)
        self.get_name_1()
        self.get_name_2(self)

    def get_name_1(self):
        try:
            print zeus.name
        except:
            print "impossible!?"

    def get_name_2(self,scope):
        print scope.name

class Maze(object):
    def get_zeus_name_1(self):
        try:
            print zeus.name
        except:
            print "can't be done!?"

    def get_zeus_name_2(self,scope):
        print scope.name

zeus=Zeus()
print 'now external calls:'
zeus.maze.get_zeus_name_1()
zeus.maze.get_zeus_name_2(zeus)
zeus.get_name_1()
zeus.get_name_2(zeus)
Run Code Online (Sandbox Code Playgroud)

输出:

can't be done!?
zeus
impossible!?
zeus
now external calls:
zeus
zeus
zeus
zeus
Run Code Online (Sandbox Code Playgroud)

在实例化期间zeus,如果__init__方法创建另一个类的实例maze,则此新实例无法访问其创建者对象zeus(除非self传递给它).(另外,如果__init__方法在其自己的类中调用方法get_name_1,则该方法也无法访问其对象属性(除非self传递给它).)

但是,在对象被实例化之后,第二个对象maze现在可以识别并访问其创建者对象,zeus.

这种行为给我带来了一些困惑和困难,因为我正在编写一些代码,其中所有内容__init__都已初始化并从序列中运行- 现在我认为最好避免这种情况.

我的问题:

  1. 为什么会这样?
  2. 是否可以通过离开实例来避免通过此方式避免出现问题__init__
  3. 还有进一步的设计含义吗?
  4. 传递self给一个新实例,似乎可能会因为自我引用而产生问题,是否也应该避免这种情况?
  5. 其他有趣的含义/我错过了什么?

谢谢你的帮助.

Sea*_*ond 5

get_zeus_name_1()正在尝试访问全局变量zeus,该变量在get_zeus_name_1()被调用时尚未初始化.

get_zeus_name_2()接受一个参数(scope)并访问它,这是有效的.它不会尝试访问全局变量zeus.

get_name_1()和相同的故事get_name_2().

我认为关键是要了解python如何执行这一行:

zeus=Zeus()
Run Code Online (Sandbox Code Playgroud)

这行告诉python:执行方法Zeus()(这是类中__init__(self)方法的另一个名称Zeus),然后将该方法返回的对象分配给全局变量zeus.

Python首先执行该方法Zeus(),然后, init方法完成执行并返回Zeus类的对象实例后,python将该对象分配给全局变量zeus.因此,在init方法完成之前,尚未定义全局变量zeus,因此get_name_1()和get_zeus_name_1()无法访问它.

get_name_2()和get_zeus_name_2()访问Zeus类的同一对象实例,因为get_name_1()和get_zeus_name_1()尝试访问,但是它们通过传递给它们的参数访问它,而不是通过全局变量访问它,所以它们不要遇到问题.

这是一个更简单的示例,演示了完全相同的问题:

>>> class Foo:
...     def __init__(self):
...         self.name = 'foobar'
...         print self.name
...         print foo.name
... 
>>> foo = Foo()
foobar
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 5, in __init__
NameError: global name 'foo' is not defined
>>> 
Run Code Online (Sandbox Code Playgroud)

print self.name行正常工作(相当于get_name_2()和get_zeus_name_2()),但该print foo.name行崩溃(相当于get_name_2()和get_zeus_name_2()).