異なるクラスのコードを分離して、それらを異なるファイルに配置したい。ただし、これらのクラスは相互に依存しています。
main.py:
from lib import A, B
def main():
a = A()
b = B()
a.hello()
b.hello()
if __name__ == '__main__':
main()
lib/_init_。py:
from a import A
from b import B
lib/a.py:
import lib.B
class A():
def __init__(self):
print "A"
def hello(self):
print "hello A"
b = B()
lib/b.py:
import lib.A
class B():
def __init__(self):
print "B"
def hello(self):
print "hello B"
a = A()
Pythonでそれを行うことは可能ですか?
編集:
このエラーメッセージが表示されます:
pydev debugger: starting
Traceback (most recent call last):
File "Eclipse-python/plugins/org.python.pydev_2.7.1.2012100913/pysrc/pydevd.py", line 1397, in <module>
debugger.run(setup['file'], None, None)
File "Eclipse-python/plugins/org.python.pydev_2.7.1.2012100913/pysrc/pydevd.py", line 1090, in run
pydev_imports.execfile(file, globals, locals) #execute the script
File "main.py", line 2, in <module>
from lib import A, B
File "lib/__init__.py", line 1, in <module>
from a import A
File "lib/a.py", line 1, in <module>
import lib.B
ImportError: No module named B
モジュールを一番上にインポートする代わりに、hello関数内で他のモジュールをインポートすることができます。
class B():
def __init__(self):
print "B"
def hello(self):
import lib.A
print "hello B"
a = A()
主な問題は、クラスをインポートしようとしているが、モジュールのインポートにのみ機能する構文を使用していることです。具体的には、A
がモジュールimport lib.A
で定義されている(そしてlib
のトップレベルの名前空間にインポートされている)クラスである場合、lib.a
は機能しません。
私が提案するのは、本当に必要でない限り、from _ import _
構文の使用を避けることです。これにより、依存関係の解決がはるかに簡単になります。
lib/a.py
:
import lib.b # note, we're not importing the class B, just the module b!
class A():
def foo(self):
return lib.b.B() # use the class later, with a qualified name
lib/b.py
:
import lib.a # again, just import the module, not the class
class B():
def foo(self):
return lib.a.A() # use another qualified name reference
lib/__init__.py
:
from a import A # these imports are fine, since the sub-modules don't rely on them
from b import B # they can be the public API for the A and B classes
a
とb
をパッケージの名前lib
に依存させたくない場合は、相対モジュールインポートを使用することもできます。
クラスAもクラスBも実際には、定義するためにもう一方がまだ存在している必要がないため、これは確実に機能します。 AのインスタンスがクラスBについて知る必要があるのはそれらがインポートされた後でのみです(逆もまた同様です)。
クラスの1つが他のクラスから継承されている場合、またはトップレベルで他のインスタンスを使用している場合は、最初にロードされたモジュールに注意する必要があります。そうしないと、まだ壊れている可能性があります。
2つのクラスが相互に依存している場合は、通常、それらが実際に同じモジュールに属しているか、依存性注入を使用して解決する必要がある結合度が高すぎることを意味します。
関数内からのインポートが「最悪の」解決策であるといういくつかのコーナーケースが実際にありますが、それでも可能な限り避ける必要があります。
一度だけインポートしたい場合は、クラスのコンストラクターでインポートして、変数をグローバルにすることができます。
class B():
def __init__(self):
global A
from lib import A
print "B"
def hello(self):
print "hello B"
a = A()
これにより、Aがグローバル変数にインポートされ、モジュール内でアクセス可能な形式になります。