Давайте рассмотрим скрипты на Python (3.x):
main.py:
from test.team import team
from test.user import user
if __name__ == '__main__':
u = user()
t = team()
u.setTeam(t)
t.setLeader(u)
тест / user.py:
from test.team import team
class user:
def setTeam(self, t):
if issubclass(t, team.__class__):
self.team = t
тест / team.py:
from test.user import user
class team:
def setLeader(self, u):
if issubclass(u, user.__class__):
self.leader = u
Теперь, конечно, у меня есть круговой импорт и великолепная ошибка ImportError.
Итак, не будучи питонистом, у меня три вопроса. Прежде всего:
я. Как я могу заставить эту вещь работать?
И, зная, что кто-то неизбежно скажет «Круговой импорт всегда указывает на проблему проектирования», возникает второй вопрос:
II. Почему этот дизайн плох?
И, наконец, третий:
III. Что было бы лучшей альтернативой?
Если быть точным, проверка типов, как указано выше, является только примером, также есть индексный слой, основанный на классе, который позволяет т.е. найти всех пользователей, являющихся членами одной команды (пользовательский класс имеет много подклассов, поэтому индекс удваивается, для пользователей в целом и для каждого конкретного подкласса) или все команды, имеющие пользователя в качестве члена
Edit:
Я надеюсь, что более подробный пример прояснит, чего я пытаюсь достичь. Файлы опущены для удобства чтения (но наличие одного исходного файла размером 300 КБ меня как-то пугает, поэтому, пожалуйста, предположите, что каждый класс находится в отдельном файле)
# ENTITY
class Entity:
_id = None
_defs = {}
_data = None
def __init__(self, **kwargs):
self._id = uuid.uuid4() # for example. or randint(). or x+1.
self._data = {}.update(kwargs)
def __settattr__(self, name, value):
if name in self._defs:
if issubclass(value.__class__, self._defs[name]):
self._data[name] = value
# more stuff goes here, specially indexing dependencies, so we can
# do Index(some_class, name_of_property, some.object) to find all
# objects of some_class or its children where
# given property == some.object
else:
raise Exception('Some misleading message')
else:
self.__dict__[name] = value
def __gettattr__(self, name):
return self._data[name]
# USERS
class User(Entity):
_defs = {'team':Team}
class DPLUser(User):
_defs = {'team':DPLTeam}
class PythonUser(DPLUser)
pass
class PerlUser(DPLUser)
pass
class FunctionalUser(User):
_defs = {'team':FunctionalTeam}
class HaskellUser(FunctionalUser)
pass
class ErlangUser(FunctionalUser)
pass
# TEAMS
class Team(Entity):
_defs = {'leader':User}
class DPLTeam(Team):
_defs = {'leader':DPLUser}
class FunctionalTeam(Team):
_defs = {'leader':FunctionalUser}
и теперь немного использования:
t1 = FunctionalTeam()
t2 = DLPTeam()
t3 = Team()
u1 = HaskellUser()
u2 = PythonUser()
t1.leader = u1 # ok
t2.leader = u2 # ok
t1.leader = u2 # not ok, exception
t3.leader = u2 # ok
# now , index
print(Index(FunctionalTeam, 'leader', u2)) # -> [t2]
print(Index(Team, 'leader', u2)) # -> [t2,t3]
Итак, он прекрасно работает (детали реализации опущены, но ничего сложного), кроме этой нечестивой циклической импорта.