Проблема фабрики классов Python, ссылающаяся на базовый класс? - PullRequest
1 голос
/ 16 апреля 2011

Недавно я столкнулся с реализацией фабрики классов Python , которая подходит к проблеме, над которой я работаю очень хорошо.Единственное отличие состоит в том, что я хотел, чтобы базовый и подклассы были в разных пакетах.

Однако, когда я пытаюсь это сделать, я сталкиваюсь с проблемой всякий раз, когда пытаюсь загрузить базовый класс.

Структура:

BaseClass.py

from subclasses import *

def NewClass():
    """Map Factory"""
    for cls in BaseClass.__subclasses__():
        print "checking class..."

class BaseClass(object):
    def __init__(self):
        print("Building an abstract BaseMap class..")

подклассы / __ init __. Py

__all__=['SubClass']

subclasses / SubClass.py

from BaseClass import BaseClass
class SubClassA(BaseClass):
    def __init__(self):
        print('Instantiating SubClassA')

Когда я пытаюсь импортировать BaseClass, я получаю следующую ошибку:

       1 #import BaseClass

 ----> 2 from BaseClass import BaseClass
       3 class SubClassA(BaseClass):
       4     def __init__(self):
       5         print('Instantiating SubClassA')

 <b>ImportError: cannot import name</b> BaseClass

Я также пытался использовать "import BaseClass", а затемподкласс «BaseClass.BaseClass», но это привело к другой ошибке:

      1 import BaseClass
----> 2 class SubClassA(BaseClass.BaseClass):
      3     def __init__(self):
      4         print('Instantiating SubClassA')

<b>AttributeError: 'module' object has no attribute 'BaseClass'</b>

Наконец, если я просто попытаюсь создать каталог подкласса, проблем не будет.Только когда я пытаюсь импортировать модуль BaseClass, что-то идет не так.

Есть идеи?

Ответы [ 2 ]

2 голосов
/ 16 апреля 2011

Некоторые эксперименты показывают, что проблема заключается в рекурсии импорта.Условное выполнение оператора импорта в BaseClass.py решило проблему для моих тестов:

if __name__ == '__main__':
    from subclasses import *

предотвращает рекурсию, и Python, похоже, удовлетворен этим.

[EDIT]

Лучшее решение - использовать метод NewClass в отдельном файле:

thing.py

from BaseClass import BaseClass
from subclasses import *

def NewClass():
    """Map Factory"""
    for cls in BaseClass.__subclasses__():
        print ("checking class...")

NewClass ()
1 голос
/ 16 апреля 2011

Без дополнительной информации кажется, что ваш модуль BaseClass не находится непосредственно на пути Python.BaseClass может найти подклассы, потому что они существуют в каталоге непосредственно под BaseClass.Обратное неверно.

A относительный импорт должен решить эту проблему.

from .. BaseClass import BaseClass

.. поднимется в каталог и будет там искать (видиз одинаковых путей к файлам).Альтернатива - поместить BaseClass непосредственно в PYTHONPATH.

Наличие двух разных модулей, зависящих друг от друга, звучит как не очень хорошая идея, хотя, если честно.Лучше всего зарегистрировать подклассы в BaseClass.

Редактировать:

То, что я имел в виду под "регистрацией в базовом классе", выглядит примерно так: '

# baseclass.py
subclasses = []
def register(cls):
    subclasses.append(cls)


# subclass.py
class SubClassA(BaseClass):
    ...

baseclass.register(SubClassA)

Теперь BaseClass не нужно знать обо всех подклассах.Они регистрируются для использования, и BaseClass может использовать их, не зная о них заранее.

...