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)
test / user.py:
from test.team import team
class user:
def setTeam(self, t):
if issubclass(t, team.__class__):
self.team = t
test / team.py:
from test.user import user
class team:
def setLeader(self, u):
if issubclass(u, user.__class__):
self.leader = u
もちろん、循環インポートと素晴らしいImportErrorがあります。
ですから、pythonistaではないので、3つの質問があります。初めに:
私。どうすればこれを機能させることができますか?
そして、誰かが必然的に「循環輸入は常に設計上の問題を示している」と言うことを知っていると、2番目の質問が来ます:
ii。なぜこのデザインは悪いのですか?
そして最後に、3番目のもの:
iii。より良い代替案は何でしょうか?
正確には、上記のタイプチェックは単なる例であり、クラスに基づくインデックスレイヤーもあります。すべてのユーザーが1つのチームのメンバーであるか(ユーザークラスには多くのサブクラスがあるため、一般的なユーザーと特定のサブクラスごとにインデックスが2倍になります)、またはすべてのチームがユーザーをメンバーとして指定していることを確認します
編集:
より詳細な例が、私が達成しようとしていることを明らかにすることを願っています。読みやすさのためにファイルを省略しました(ただし、300kbのソースファイルが1つあると、どういうわけか怖いので、すべてのクラスが異なるファイルにあると想定してください)
# 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]
したがって、この不潔な循環インポートのほかに、それはうまく機能します(実装の詳細は省略されていますが、複雑なことは何もありません)。