Страницы

Поиск по вопросам

вторник, 24 декабря 2019 г.

Опциональная типизация в python: проблемы с импортами

#python #python_3x #архитектура #python_35


Пишу на python 3.5, пробую пользовать типизацию, но столкнулся с проблемой циклического
импортирования - стало сложно разбивать программу на модули.

Одна из проблем отношение одни_к_одному:

# модуль 1
from mod1 import B

class A:
    def __init__(self):
        self.__B = B(self)

# модуль 2
from mod2 import A

class B:
    def __init__(self, arg: A):
        self.__a = arg


Ну и так далее. Проблема серьёзно нарастает с увеличением количества модулей.

Хочу узнать это я к задаче подхожу неверно, или есть решение проблемы?

ПС: я в том смысле, что возбуждается исключение ImportError, и я не могу от него
избавиться.
    


Ответы

Ответ 1



PEP 484 -- Type Hints рекомендует использовать import module вместо from module import Type и задавать типы в виде строк, чтобы уменьшить последствия от круговой зависимости, вызванной использованием type hints: # mod1.py import mod2 class B: def __init__(self, arg: 'mod2.A') -> None: self.__a = arg # mod2.py import mod1 class A: def __init__(self): self.__b = mod1.B(self) В качестве альтернативы, если классы настолько тесно связаны, можно их в один модуль поместить или выполнить другой подходящий случаю refactoring (возможно более общий тип, определённый, к примеру, в mod2.types, следует использовать в B). See Type hinting would generate a lot of import statements (possibly leading to circular imports). Use strings instead of imported names?

Ответ 2



def modCreator(): print(''' class A: def __init__(self): from mod1 import B self._B = B(self)''', file=open('mod2.py', 'w')) print(''' from mod2 import A class B: def __init__(self, arg: A): self._a = arg''', file=open('mod1.py', 'w')) if __name__ == '__main__': modCreator() from mod1 import B from mod2 import A a = A() b = B(A) print(a, a._B) print(b, b._a) out:

Ответ 3



def modCreate(): modules = {} modules['A.py'] = ''' from G import glob class A: def __init__(self, x: glob.B): self.x = x self.B = glob.B(self) glob.A = A ''' modules['B.py'] = ''' from G import glob class B: def __init__(self, x: glob.A): self.x = x glob.B = B ''' modules['G.py'] = ''' class Glob: def __getattr__(self, class_: object): print('skip %s' % class_) glob = Glob() ''' for module, code in modules.items(): print(code, file=open(module, 'w')) if __name__ == '__main__': modCreate() from B import B from A import A from G import glob print(glob, [[c, getattr(glob, c)] for c in dir(glob) if not c.startswith('_')]) a = A(B) print(a, a.x, a.B) b = B(A) print(b, b.x) print(A == glob.A) out: skip A [['A', ], ['B', ]] True

Комментариев нет:

Отправить комментарий