Как вы боритесь с циклическими импортами в Python?

Слушайте люди, как вы боритесь с циклическими импортами в питоне?
На больших проектах это прям становится какой то большой проблемой если вы используете статические типы данных в аргументах функции. Давайте сразу пример:

main.py

from Article import Article
from User import User

if __name__ == '__main__':
    pass


User.py
from Article import Article

class User:
    def __int__(self, name: str):
        self.name = name

    def fetch_article(self) -> list[Article]:
        """
        Returns all the user's articles
        :return:
        """
        return [Article(), Article()]  # Just for example


Article.py
from User import User


class Article:

    def __int__(self, title: str, user: User):
        self.title = title
        self.user = user


Traceback (most recent call last):
File "/home/master/PycharmProjects/example/main.py", line 1, in
from Article import Article
File "/home/master/PycharmProjects/example/Article.py", line 1, in
from User import User
File "/home/master/PycharmProjects/example/User.py", line 1, in
from Article import Article
ImportError: cannot import name 'Article' from partially initialized module 'Article' (most likely due to a circular import) (/home/master/PycharmProjects/example/Article.py)


Собственно простая задача, есть статьи, есть пользователи которые их написали, и для примера мы хотим добавить
в модель пользователя метод который дергает все написанные им статьи.
Как цивилизованный человек я всегда указываю типы данных которые ожидаю на входе, и которые ожидаю на выходе.
Это нормальная практика, я пишу не на одном языке, и обычно это не вызывает проблем например в том же PHP ибо там есть магические __autoload.php который помогает избегать циклических импортов. Однако в питоне такой штуки нету.
А отказываться от явного указания типов аргументов я не хочу. Это дурной тон, грязный код, и ворох багов в будущем, да еще и призрение тестировщика... Короче хочу спросить у бородатых и опытных, как вы разруливаете данные проблемы в проекте? какие средства для этого есть? Ведь сказать что с точки зрения написания чистого кода, код выше неправильный нельзя.
  • Вопрос задан
  • 1852 просмотра
Решения вопроса 1
Vindicar
@Vindicar
RTFM!
Если речь идёт об импорте только ради type hinting, то typing.TYPE_CHEKING в помощь.
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 2
@yakov_the_kaktus
Попробуйте импортировать то, что вам надо локально:
def your_function_or_method():
     from User import User
     ...
Ответ написан
Комментировать
@gimntut
Я ориентируюсь на линтер PyCharm, он позволяет использовать типы до импортов
from typing import TYPE_CHECKING, List

def get_cat_list() -> List["Cat"]
  from animals import Cat

  return [Cat() for _ in range(3)]

if TYPE_CHECKING:
  from animals import Cat

Возможно mypy покажет на таком коде ошибку.
В данном примере pycharm подсветит ошибку, если забыть сделать импорт внутри функции.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы