2012-05-28 4 views
18

В Python можно ли получить объект, скажем Foo, который содержит другой объект, Bar, изнутри самой панели? Вот пример того, что я имею в виду:Получение контейнера/родительского объекта изнутри python

class Foo(object): 
    def __init__(self): 
     self.bar = Bar() 
     self.text = "Hello World" 

class Bar(object): 
    def __init__(self): 
     self.newText = foo.text #This is what I want to do, 
           #access the properties of the container object 

foo = Foo() 

Возможно ли это? Благодаря!

+2

У вас есть опечатка; в 'Foo .__ init__',' self.bar = Foo() 'должно быть' self.bar = Bar() '. В противном случае у вас есть бесконечный цикл (чтобы создать Foo, вам сначала нужно создать Foo). –

+0

Спасибо, исправлено! :) –

ответ

29

Передайте ссылку на объект Bar, например, так:

class Foo(object): 
    def __init__(self): 
     self.text = "Hello World" # has to be created first, so Bar.__init__ can reference it 
     self.bar = Bar(self) 

class Bar(object): 
    def __init__(self, parent): 
     self.parent = parent 
     self.newText = parent.text 

foo = Foo() 

Edit: как указал @thomleo, это может вызвать проблемы со сбором мусора. Предлагаемое решение выложена на http://eli.thegreenplace.net/2009/06/12/safely-using-destructors-in-python/ и выглядит как

import weakref 

class Foo(object): 
    def __init__(self): 
     self.text = "Hello World" 
     self.bar = Bar(self) 

class Bar(object): 
    def __init__(self, parent): 
     self.parent = weakref.ref(parent) # <= garbage-collector safe! 
     self.newText = parent.text 

foo = Foo() 
+0

Спасибо, это работает. Единственная проблема, которую я вижу в этом, заключается в том, что когда я пытаюсь получить доступ ко многим объектам, я буду звонить на родительский .parent.parent.etc. Есть ли более простой способ сделать это? –

+3

Если я не ошибаюсь, есть и серьезная проблема. Когда вы пытаетесь выполнить 'del foo'', он не обязательно будет уничтожать его, поскольку ссылка на него все еще существует в атрибуте' .parent'' '' Bar'', который он содержит ... –

+0

@MichaelMcClenaghan, в этом случае вы можете просто перебирать несколько раз, вместо того, чтобы вручную указывать его. Конечно, это зависит от структуры ... – batbrat

4

возможно получить объект, скажем Foo, который содержит другой объект, Бар, из самого бара?

Не «автоматически», потому что язык не построен таким образом, и, в частности, язык построен таким образом, что нет возможности гарантировать, что Foo существует.

Тем не менее, вы всегда можете сделать это явно. Атрибуты, как и любой другой идентификатор в Python, - это просто имена, а не пространство для хранения данных; поэтому ничто не мешает вам предоставить экземпляр Bar назначенный вручную атрибут foo, являющийся экземпляром Foo, и наоборот в то же время.

-3

Что об использовании наследования:

class Bar(object): 
    def __init__(self): 
     self.newText = self.text 

class Foo(Bar): 
    def __init__(self): 
     self.txt = 'Hello World' 
     Bar.__init__(self) 

foo = Foo() 
print foo.newText 
Смежные вопросы