У всех динамических языков есть проблема кругового импорта? - PullRequest
4 голосов
/ 18 февраля 2010

Для следующего кода Python:

first.py

# first.py
from second import Second

class First:
    def __init__(self):
        print 'Second'

second.py

# second.py
from first import First

class Second:
    def __init__(self):
        print 'Second'

После создания файлов и запуска из оболочки следующего:

python first.py

Я получаю сообщение об ошибке: ImportError: cannot import name Second

У других динамических языков, таких как Ruby, есть такая проблема? Причина, по которой я спрашиваю, заключается в том, что я столкнулся с этой проблемой в проекте Django, где две модели зависят друг от друга. Я знаю, что возможными решениями являются перепроектирование проекта или импорт по запросу. Я просто хочу знать, сталкивались ли разработчики с другими динамическими языками с этой проблемой.

Ответы [ 6 ]

12 голосов
/ 18 февраля 2010

Python в некоторой степени может обрабатывать циклический импорт.В тех случаях, когда никакого смысла не может быть, решение, вероятно, все еще не имеет смысла на другом языке.Большинство проблем можно устранить с помощью import first и позже, ссылаясь на first.First вместо from first import First.

Было бы лучше, если бы вы могли переместить общий код в его собственный модуль или каким-либо образом реорганизовать необходимость кругового импорта. Круговой импорт всегда указывает на проблему проектирования.

3 голосов
/ 18 февраля 2010

Рекурсивные определения - не проблема, ограниченная динамическими языками. Это также часто проблема в статически типизированных языках. Может отображаться как ошибка компиляции, поскольку один из типов будет использоваться до его определения.

В некоторых языках решение заключается в использовании предварительных объявлений. Другие языки решают проблему, компилируя более одного файла одновременно.

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

2 голосов
/ 18 февраля 2010

Все остальные постеры верны, что циклический импорт является серьезной проблемой, которую вы должны исправить структурно.

Однако, особенно в моделях Python / Django, вы можете использовать строковые имена для настройки внешних ключей, чтобы избежать этих циклических операций.проблемы с зависимостями -

#appA/models.py
class A(models.Model):
  b = models.ForeignKey('appB.b')

#appB/models.py
class B(models.Model):
  a = models.ForeignKey('appA.a')

Циркулярные ссылки в таблицах БД не обязательно плохи (но не всегда хороши);Django позволяет определять ключи со строкой, чтобы помочь в ситуациях, когда это необходимо.Если вам действительно нужно создать два экземпляра внутри друг друга, у вас возникнут большие проблемы.

1 голос
/ 18 февраля 2010

Обратите внимание, что если вы просто перенесете импорт в конец модуля, циклический импорт будет работать, как и ожидалось. Вот так:

first.py

# first.py
class First:
  def __init__(self):
    print 'Second'
from second import Second

second.py

# second.py
class Second:
    def __init__(self):
        print 'Second'
from first import First

Ссылка на импорт Фредрика Лунда стоит прочитать. Однако, как советуют другие, лучше всего переустанавливать код, чтобы полностью избежать циклического импорта.

1 голос
/ 18 февраля 2010

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

0 голосов
/ 18 февраля 2010

Это не проблема, связанная с "динамическими" языками.Это архитектурная проблема.Вы должны лучше взглянуть на то, как вы структурировали вещи.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...