2017-02-16 4 views
2

У меня есть 2 класса (определения типа GraphQL), которые зависят друг от друга. Я хотел бы переместить их в отдельные файлы.Взаимозависимые классы в отдельных файлах (круговой импорт)

Если они определены в одном файле, никаких проблем.

# all_schemas.py 

class AuthorSchema(graphene.ObjectType): 
    publications = graphene.List(lambda: PublicationSchema) 


class PublicationSchema(graphene.ObjectType): 
    author = graphene.Field(AuthorSchema) 

Как только я помещаю их в отдельные файлы, я сталкиваюсь с проблемой «циклического импорта».

author_schema.py

from publication_schema import PublicationSchema 

class AuthorSchema(graphene.ObjectType): 
    publications = graphene.List(lambda: PublicationSchema) 

publication_schema.py

from author_schema import AuthorSchema 

class PublicationSchema(graphene.ObjectType): 
    author = graphene.Field(AuthorSchema) 

Вот то, что ошибка, которую я считаю, чтобы показать круговой вопрос импорта:

Каковы мои варианты для решения этой проблемы?

Некоторые люди говорили, что круговой импорт - это плохая практика, я не понимаю, почему это было бы здесь, но я хотел бы узнать почему. Они также предлагают реорганизовать код, но мне интересно, как это сделать точно, не заканчивая одним огромным файлом, который содержит все взаимозависимые классы.

(Обратите внимание, что я использую Python 2.7, на Google App Engine)

+0

Это плохая практика, потому что в вашем случае невозможно создать структуру класса 'PublicationSchema', не зная, что означает' AutorSchema' (атрибут 'PublicationSchema'' author' зависит от автора), но вы не можете создать ' AutorSchema', в первую очередь потому, что атрибут 'публикаций' зависит от' PublicationSchema'. Это делает всю структуру нелогичной, и интерпретатор Python не может понять, чего вы хотите достичь. – zwer

+0

спасибо @zwer, что я не понимаю, так это: логическая концепция работает нормально, пока все определено в том же файле. Единственное, что я пытаюсь сделать, это переустановить код, а (рабочая) логика останется точно такой же ... – Hoff

+0

Он застревает в импорте, потому что это первая команда, поэтому интерпретатор пытается загрузить любой модуль, который вы ему даете. При использовании двух взаимосвязанных зависимостей, когда он пытается загрузить зависимость, она возвращается к файлу, из которого он пришел, из-за чего он не анализирует второй файл (чтобы избежать бесконечного цикла) и, таким образом, не загружает зависимости. Когда классы находятся в одном файле, Python может разрешить циклическую зависимость, поскольку сначала создает указатели на сами классы, а не пытается сначала загрузить их. – zwer

ответ

0

Стандартный питона трюк, чтобы избежать циклических зависимостей, чтобы избежать их работы во время импорта. Вместо того, чтобы ставить. Например, введите from author_schema import AuthorSchema в класс PublicationSchema, поэтому он не запускается в то время, когда этот класс импортируется из AuthorSchema. Тем не менее, это нестабильно, точная точка для их ввода зависит от кода и может измениться по мере изменения кода.

Стандартный подход ООП предназначен для AuthorInterface, который импортирует публикация и автор реализует. См. Принцип ациклических зависимостей и Принцип инверсии зависимостей.

0

выше комментарий стоя, если вы действительно, действительно должны сделать это (и вы не делаете!), Вы всегда можете использовать отложенный импорт в вашем AuthorSchema:

def get_publication_schema(): 
    from publication_schema import PublicationSchema 
    return PublicationSchema 

class AuthorSchema(graphene.ObjectType): 

    publications = graphene.List(get_publication_schema) 

Протест - вы все равно выиграл» t выполнить любой код, который вызывает PublicationSchema из «глобального» пространства autor_schema.py, поскольку оба файла должны быть полностью загружены, чтобы ссылаться друг на друга. Но в сценарии использования сторонних разработчиков это будет работать.

+0

привет @zwer, очень ценю, что вы нашли время, чтобы помочь мне. Вы говорите: «Если вам действительно нужно действительно делать это (и вы этого не делаете!) ...« Посредством «сделайте это», я предполагаю, что вы имеете в виду «поместить 2 взаимозависимых класса в отдельные файлы» - хорошо, я «Мне нужно это сделать, но так я хотел бы структурировать свой код - или это необоснованная цель в вашем варианте? – Hoff

+0

Как @blue_note, упомянутое выше, наличие взаимосвязанных зависимостей идет вразрез с принципами ООП. Вы можете сделать это с помощью ленивого импорта, как упоминалось выше, но затем вы технически заставляете язык использовать свою идею структуры, чем то, что воспринимается как хороший подход ООП (явное дерево зависимостей для начинающих). Поскольку все, в конце концов, превращается в процессуальное выполнение, попробуйте выполнить последовательность выполнения, и вы поймете, почему Python жалуется - это двусмысленность, которая отбрасывает ее с wack. – zwer

+0

И для того, чтобы быть ясным, я сказал, что вам больше не нужно это предложение, чтобы переосмыслить свою структуру, поскольку должен быть способ достижения ваших целей, не противоречив текстуре вашего компилятора/интерпретатора и не жертвуя явным владением/структура зависимостей. – zwer

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