2009-06-25 3 views
6

У меня есть два класса, которые ссылаются друг на друга, но, очевидно, компилятор жалуется. Есть ли способ обойти это?классы python, которые ссылаются друг на друга

EDIT

На самом деле мой код немного отличается от того, что использует Hank Gay. Таким образом, python может определенно иметь дело с некоторыми видами циклических ссылок, но он бросает ошибку в следующей ситуации. Ниже приводится то, что у меня есть, и я получаю «имя Y, не определенную ошибку»

class X(models.Model): 

     creator = Registry() 
     creator.register(Y) 

class Y(models.Model): 
    a = models.ForeignKey(X) 
    b = models.CharField(max_length=200) 

Надеюсь, что это поможет уточнить. Какие-либо предложения.

+4

Что "очевидно"? Где он жалуется? Показать код? Циркулярные ссылки не проблема для Python, проблема кроется в другом месте. –

+0

Как выглядит код? –

+0

wow ... * rolleyes * – Robbie

ответ

15

В python код в классе запускается при загрузке класса.

Теперь, что, черт возьми, это значит? ;-)

Рассмотрим следующий код:

class x: 
    print "hello" 
    def __init__(self): print "hello again" 

При загрузке модуля, который содержит код, питон будет печатать hello. Всякий раз, когда вы создаете x, python будет печатать hello again.

Вы можете придумать def __init__(self): ... как эквивалент с __init__ = lambda self: ..., за исключением того, что не применяются ограничения на лямбда python. То есть def - это назначение, которое может объяснить, почему запущены методы вне кода, но не внутренние.

Когда ваш код говорит

class X(models.Model): 
    creator = Registry() 
    creator.register(Y) 

Вы ссылаетесь Y, когда модуль загружен, перед тем Y имеет значение. Вы можете думать о class X как задание (но я не могу вспомнить синтаксис для создания анонимных классов экспромтом, может быть, это призывание type?)

Что вы можете сделать это:

class X(models.Model): 
    pass 
class Y(models.Model): 
    foo = something_that_uses_(X) 
X.bar = something_which_uses(Y) 

То есть, создайте атрибуты класса X, которые ссылаются на Y после Y. Или наоборот: сначала создайте Y, затем X, а затем атрибуты Y, которые зависят от X, если это проще.

Надеется, что это помогает :)

2

ОБНОВЛЕНИЕ: Он изменил вопрос после моего ответа. В настоящее время принятое решение лучше в свете нового вопроса.

Что вы говорите, это проблема?

class A(object): 
    def __init__(self): 
     super(A, self).__init__() 


    def b(self): 
     return B() 


class B(object): 
    def __init__(self): 
     super(B, self).__init__() 


    def a(self): 
     return A() 

Это компилируется и работает отлично.

+0

Дополнительная информация: Это работает, да. Но он поставляется с ценой: он работает, только если вы поместите все классы в один файл. Это довольно неудобно: это может быть очень pythonic, я не знаю, но я знаю, что это ломается с хорошей практикой OOP использования собственного файла для каждого (общедоступного) класса. –

2

Пока вы работаете в рамках метода, вы можете получить доступ к объекту класса.

Таким образом, приведенный выше пример не имеет проблем, если creator.register(Y) перемещен внутри __init__. Однако вы не можете иметь круговые ссылки на классы вне методов.

+1

Этот ответ ничего не объясняет. Это дает «обходной путь» без понимания или объяснения реальной проблемы, что объясняется в ответах Джонаса и Джона Мачина. –

2

Ошибки в том, что выполнение creator.register(Y) попытке в течение (исполняемое) определения класса X, и на этом этапе, класс Y не определенно. Понимают это: class и def - это операторы, которые выполняются (как правило, во время импорта); они не являются «декларациями».

Предложение: сообщите нам, чего вы пытаетесь достичь - возможно, как новый вопрос.

-2

Проблема, скорее всего, не Python. Я бы подумал, что это проблема SQL. Классы через слой абстракции, преобразованный в SQL-запрос, создают таблицу. Вы пытаетесь ссылаться из одной таблицы другой, которая пока не существует.

В SQL вы бы решить эту проблему путем создания таблицы первой без ссылок и после этого изменить их, чтобы сделать эти ссылки,

Однако я не уверен, что мой ответ, так возьмите его с большим количеством приправ, я был бы действительно удивлен, если слой абстракции базы данных Django не будет иметь дело с перекрестными ссылками.

Смежные вопросы