#python
Вопрос:
У меня два класса Img
, и ImgAnalyzer
у каждого свой модуль. ImgAnalyzer
принимает Img
объект в качестве параметра и выполняет над ним различные анализы, но я хочу, чтобы Img
объект «принадлежал» ImgAnalyzer
объекту, т. Е. Если я хочу использовать анализатор, мне нужно использовать его через изображение.
экс:
img.py
from img_analyzer import ImgAnalyzer
class Img:
def __init__(self, *args, **kwargs):
# do thing
self.analyzer = ImgAnalyzer(self)
# other funcs
img_analyzer.py
from img import Img
class ImgAnalyzer:
def __init__(self, img: Image):
# do thing
# other funcs
Затем я мог получить доступ к анализатору с изображения:
img = Img(params)
img.analyzer.func()
Это неизбежно приводит к циклической ошибке импорта.
Классы должны быть в отдельных файлах, потому что они имеют разные функции и в любом случае слишком длинные, чтобы их можно было разумно объединить. Я посмотрел здесь и на других сайтах, но не смог понять, как это исправить.
Как я могу управлять классом и зависеть от другого класса, не вызывая ошибок?
Комментарии:
1.
ImgAnalyzer
Действительно ли нужно импортироватьImg
? Представляется вероятным, что все, что делает анализатор, он делает с помощью метода или атрибутаImg
переданного ему объекта, который не требует импорта.2. @jasonharper Разве то, как я это структурировал, не является плохой практикой? И, если мне нужно проверить, что переданный параметр является
Img
объектом, например, для обработки ошибок, мне понадобится инструкция import.
Ответ №1:
Короче говоря, не надо.
Циклический импорт уже является достаточно плохой попыткой совместного использования кода между двумя файлами/модулями. Похоже, вам нужно что-то более похожее на директиву include, найденную на других языках, но даже в этом случае циклическое включение вызывает ошибки. Ваше дело усугубляется тем фактом, что у вас есть циклически зависимые экземпляры. Создание экземпляра циклического класса в Python законно, но это беспорядочно и не может быть разделено на отдельные файлы.
В вашем случае кажется, что вы используете ImgAnalyzer
расширенный пакет методов для Img
; вы даже называете его таковым img.analyzer.func()
. Вы можете выполнить ту же функциональность, отделив классы друг от друга и сделав импорт односторонним. Идентичность каждого экземпляра ImgAnalyzer
полностью зависела от экземпляра Img
, поэтому, как только мы его разделим, нам даже не ПОНАДОБИТСЯ класс:
# img_analyzer.py
def func(img):
# do stuff on img, intended to be Img instance
import img_analyzer
class Img:
def __init__(self, *args, **kwargs):
# do thing
# other funcs
pic1 = Img(params)
img_analyzer.func(pic1)
Синтаксически это не похоже Img
на owns img_analyzer
или func
, но в вашем исходном коде этого тоже не было. func
раньше принадлежал к ImgAnalyzer
классу и мог использоваться как ImgAnalyzer.func(ImgAnalyzer(img), img)
, для чего img.analyzer.func()
был просто синтаксический сахар. img_analyzer.func(pic1)
так же аккуратно и лаконично, избегая при этом циклической зависимости. func
все еще принадлежит Img
в том смысле, что он был разработан специально для Img
экземпляров.
Ответ №2:
Предполагая, что вам нужно импортировать Img
только img_analyzer.py
для проверки типа
Вы можете использовать константу TYPE_CHECKING модуля ввода
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from img import Img
class ImgAnalyzer:
def __init__(self, img: 'Image'):
# do thing
# other funcs
Согласно typing
документации, typing.TYPECHECKING
это специальная константа, которая предполагается True
сторонними контролерами статического типа. Это происходит False
во время выполнения