Как импортировать модули, содержащие классы с круговой зависимостью? - PullRequest
1 голос
/ 11 февраля 2020

Предположим, у меня есть следующие base и child

class Base:

    def __new__(cls, *args):
        if cls is Base:
            if len(args) < 2:
                return Child1.__new__(Child1, *args)

            return Child2.__new__(Child2, *args)

        return super().__new__(cls)

    def __init__(self, arg):
        self.common_arg = arg


class Child1(Base):
    def __init__(self, arg0=None):
        super().__init__(arg0)



class Child2(Base):
    def __init__(self, arg0, arg1, *args):
        super().__init__(arg0 + arg1)

        self.args = list(args).copy()

Между классами явно существует круговая зависимость, но, пока все классы определены в одном модуле, это не вызывает никаких проблемы.

Теперь, как мне разделить их на три модуля (в одном пакете)?

Я сделал разделение на три файла:

package/
    __init__.py
    base.py
    ch1.py
    ch2.py

со следующим содержимым :

# base.py ############################################################

from . import ch1, ch2

class Base:

    def __new__(cls, *args):
        if cls is Base:
            if len(args) < 2:
                return ch1.Child1.__new__(ch1.Child1, *args)

            return ch2.Child2.__new__(ch2.Child2, *args)

        return super().__new__(cls)

    def __init__(self, arg):
        self.common_arg = arg


# ch1.py ############################################################
from . import base

class Child1(base.Base):
    def __init__(self, arg0=None):
        super().__init__(arg0)

# ch2.py ############################################################
from . import base


class Child2(base.Base):
    def __init__(self, arg0, arg1, *args):
        super().__init__(arg0 + arg1)
        self.args = list(args).copy()   

как предложено здесь но это не работает.

import package.ch1

повышает

AttributeError: module 'package.base' has no attribute 'Base'

1 Ответ

0 голосов
/ 11 февраля 2020

Заставьте своих пользователей вызывать заводскую функцию:

def make_base(*args):
    if len(args) < 2:
        return Child1(*args)

    return Child2(*args)


class Base:
    def __init__(self, arg):
        self.common_arg = arg


class Child1(Base):
    pass        # Child1 automatically inherits Base.__init__()


class Child2(Base):
    def __init__(self, arg0, arg1, *args):
        super().__init__(arg0 + arg1)

        self.args = list(args).copy()

Теперь каждая часть кода выше может быть разбита на отдельный файл.

...