Привет!
Ничто не может быть более вкусным для питона, чем курица и яйца. Итак, сегодня наш Python решил решить старый философский вопрос: что было первым, курица или яйцо. Чтобы сделать это, он решил создать два класса, а затем выполнить некоторое моделирование, чтобы получить окончательный ответ на этот вопрос.
Хорошо, давайте начнем. Наш Python-это дранная PA всех питонов, а серийный номер-2,7. Для начала он создал 3 файла:
# filename: models/egg.py import models.chicken class Egg(object): def __init__(self, name): super(Egg, self).__init__() self.name = name def wait(self): return models.chicken.Chicken("Chicken from [{self.name}]".format(self=self))
# filename: models/chicken.py import models.egg class Chicken(object): def __init__(self, name): super(Chicken, self).__init__() self.name = name def create_egg(self): return models.egg.Egg("Egg of [{self.name}]".format(self=self))
# filename: main.py import models.chicken if __name__ == '__main__': # Decision maker! c = models.chicken.Chicken("Ryaba") print(c.create_egg().wait().create_egg().name)
Grand-Pa Python доволен результатами:
$ python2.7 main.py Egg of [Chicken from [Egg of [Ryaba]]]
Для тех из вас, кто скептически относится к круговой зависимости в Python – да, они поддерживаются, но только в некоторой степени. Как правило, когда интерпретатор видит Импорт модели.egg
Он проверяет, импортируется ли этот модуль и, если он есть, использует адрес этого модуля из кэша. Если это не так, он сразу же создает запись в кэше, а затем начинает делать фактический импорт. Вот почему, если у вас есть только Import
Заявления в вашем коде вы в безопасности.
Как только мы решим использовать от
Заявление, наши круговые зависимости не смогут быть разрешены. Давай попробуем!
# filename: models/egg.py from models.chicken import Chicken class Egg(object): def __init__(self, name): super(Egg, self).__init__() self.name = name def wait(self): return Chicken("Chicken from [{self.name}]".format(self=self))
# filename: models/chicken.py from models.egg import Egg class Chicken(object): def __init__(self, name): super(Chicken, self).__init__() self.name = name def create_egg(self): return Egg("Egg of [{self.name}]".format(self=self))
$ python2.7 main.py Traceback (most recent call last): File "main.py", line 1, inimport models.chicken File "/data/models/chicken.py", line 1, in from models.egg import Egg File "/data/models/egg.py", line 1, in from models.chicken import Chicken ImportError: cannot import name Chicken $ python3.7 main.py Traceback (most recent call last): File "main.py", line 1, in import models.chicken File "/data/models/chicken.py", line 1, in from models.egg import Egg File "/data/models/egg.py", line 1, in from models.chicken import Chicken ImportError: cannot import name 'Chicken' from 'models.chicken' (/data/models/chicken.py)
Это более или менее предсказуемо, и это настоящая проблема с курицей-яйцом. Чтобы импортировать Курица
класс в яйцо
Модуль вам нужно проанализировать курица
Модуль (Итак, просто адрес модуля недостаточно), и для полного разбора курица
Модуль, вам нужно завершить анализ яйцо
модуль. Итак, ни за что.
ХОРОШО. И теперь мне нужно ваше полное внимание: мы собираемся заменить Импорт <пакет>. <Модуль>
по Из
Анкет
# filename: models/egg.py from models import chicken class Egg(object): def __init__(self, name): super(Egg, self).__init__() self.name = name def wait(self): return chicken.Chicken("Chicken from [{self.name}]".format(self=self))
# filename: models/chicken.py from models import egg class Chicken(object): def __init__(self, name): super(Chicken, self).__init__() self.name = name def create_egg(self): return egg.Egg("Egg of [{self.name}]".format(self=self))
И результат немного неожиданно:
$ python2.7 main.py Traceback (most recent call last): File "main.py", line 1, inimport models.chicken File "/data/models/chicken.py", line 1, in from models import egg File "/data/models/egg.py", line 1, in from models import chicken ImportError: cannot import name chicken $ python3.7 main.py Egg of [Chicken from [Egg of [Ryaba]]]
Таким образом, Python3 изменил способ импорта пакетов, как правило, они добавляются к Sys.Modules раньше, чем Python2. Хорошо знать.
И последний сюрприз на сегодня. Теперь мы используем Импорт
синтаксис.
# filename: models/egg.py import models.chicken as chicken class Egg(object): def __init__(self, name): super(Egg, self).__init__() self.name = name def wait(self): return chicken.Chicken("Chicken from [{self.name}]".format(self=self))
# filename: models/chicken.py import models.egg as egg class Chicken(object): def __init__(self, name): super(Chicken, self).__init__() self.name = name def create_egg(self): return egg.Egg("Egg of [{self.name}]".format(self=self))
И можете ли вы предсказать выход?
$ python2.7 main.py Traceback (most recent call last): File "main.py", line 1, inimport models.chicken File "/data/models/chicken.py", line 1, in import models.egg as egg File "/data/models/egg.py", line 1, in import models.chicken as chicken AttributeError: 'module' object has no attribute 'chicken' $ python3.6 main.py Traceback (most recent call last): File "main.py", line 1, in import models.chicken File "/data/models/chicken.py", line 1, in import models.egg as egg File "/data/models/egg.py", line 1, in import models.chicken as chicken AttributeError: module 'models' has no attribute 'chicken' $ python3.7 main.py Egg of [Chicken from [Egg of [Ryaba]]]
Python3.7 Won:) ОК. Здесь действительно произошло то, что был ошибка в Импорт A.B.C As D
Синтаксис, который был Исправлено В версии 3.7.
Спасибо за чтение!
Оригинал: “https://dev.to/xni/solving-the-chicken-egg-problem-with-python-4ocn”