Импорт подкласса из базового класса в Python - PullRequest
4 голосов
/ 30 ноября 2011

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

Раньше это работало, помещая подклассы и базовый класс в один файл и делая что-то вроде globals()[name].

Однако теперь я разделил подклассы на другие файлы. У каждого из них есть оператор import base вверху, поэтому я не могу просто импортировать подклассы в моем базовом классе, иначе будет цепочка циклического импорта.

Есть ли обходной путь для этого?

In base.py :

from basefactory import BaseFactory
class Base:
    def __init__(self, arg1, arg2):
        ...
    def resolve(self, element):
        className = typing.getClassName(element)
        return BaseFactory.getInstance(className, element, self)

В basefactory.py :

from file1 import *
from file2 import *
...
class BaseFactory:
    @staticmethod
    def getInstance(name, arg1, arg2):
       subclass = globals()[name]
       return subclass(arg1, arg2)

In file1.py :

from base import Base

class subclass1(Base):
    def foo(self):
        return self.arg1

Ответы [ 3 ]

5 голосов
/ 30 ноября 2011

Из того, что я понимаю, у вас есть:

  1. Базовый класс
  2. Серия производных классов от базового класса
  3. Метод фабрики в базовом классе, который создает правильный тип производного класса
  4. Производные классы разбиты на файлы, и они зависят от базового класса, но метод фабрики в базовом классе зависит от производных классов

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

Например:

# base.py:
class baseClass():
   def __init__(self):
      self.name = "Base"

# sub1.py:
from base import baseClass
class sub1Class(baseClass):
   def __init__(self):
      self.name = "sub1"

# sub2.py:
from base import baseClass
class sub2Class(baseClass):
   def __init__(self):
      self.name = "sub2"

# factory.py:
from sub1 import sub1Class
from sub2 import sub2Class # should not create an error
mapping = {'sub1': sub1Class, 'sub2': sub2Class}

def create(baseType):
  return mapping[baseType]

На самом деле, лучшим способом может быть использование type :

type(name, bases, dict) возвращает объект нового типа. По сути, это динамическая форма выражения класса. Строка имени является именем класса и становится атрибутом __name__; кортеж базовых элементов классифицирует базовые классы и становится атрибутом __bases__; и словарь dict является пространством имен, содержащим определения для тела класса, и становится атрибутом __dict__. Например, следующие два оператора создают идентичные объекты типа:

>>> class X(object):
...     a = 1
...
>>> X = type('X', (object,), dict(a=1))

Почему бы не переместить решимость в класс менеджера? Взгляните на класс домена в Фабрика классов в Python . Я не уверен, что требуется разрешение ... вы можете получить имя класса непосредственно из self.__class__.__name__ и использовать такие функции Python, как type() и isinstance(), чтобы проверить, являются ли они определенными типами.

Также проверьте:
Можете ли вы использовать строку для создания экземпляра класса в Python?
Имеет ли python эквивалент Java Class.forName ()?

4 голосов
/ 30 ноября 2011

Вы можете переместить оператор import, который не выполняется, в метод, который создает объект подкласса.

0 голосов
/ 30 ноября 2011

Не знаю, понимаю ли я вас, почему вы берете подклассы из класса, если они вам нужны внутри? Пусть тогда внутри класса и, где бы они вам ни понадобились, вы можете from class import subclass

...