あなたは確かにchild
をparent
とparent
からchild
にインポートできます。この作業を行うための鍵はparent
モジュールが部分的にロードされるのは、Pythonがモジュールレベルコードchild
を実行しているときにのみロードされるため、child
はモジュールレベルのコードからparent
に深くプローブしないことです。(parent
実行のモジュールレベルで
- コードは、それが
child
をロードするステートメントを達するまでimport child
次のいずれか は、ここでは、(最初にロードされるparent
を想定)child
からparent
とparent
からchild
をインポートするときに何が起こるかですまたはfrom child import something
)。 "モジュールレベル"とは、クラスや関数定義に含まれていないステートメントを意味します。モジュールレベルで定義されたクラスと関数も、モジュール内のオブジェクトとして作成されます。ただし、関数とクラスメソッド自体はまだ実行されません。
parent
のコードレベルでimport child
の文(または同等のもの)を取得すると、parent
コードの実行が停止し、child
にモジュールレベルのコードが実行されます。 child
がimport parent
またはfrom parent import something
でparent
をインポートした場合、部分的に構成された現在の状態のparent
モジュールが得られます。したがって、child
のモジュールレベルのコードでは、の下に定義されたオブジェクトには、parent.py
にアクセスできません。
child
のモジュールレベルコードの実行が終了すると、制御はimport child
ステートメントの下のparent
に戻り、モジュールレベルコードのすべてがparent
で実行されます。
child
のモジュールレベルのコードは、(child
負荷parent
が部分的にしか完了しているので)import child
文の後parent
で定義されているオブジェクトにアクセスしようとすると、このプロセスはあなたに迷惑を与えるだろう。これを解決するには、child
のモジュールレベルでparent
をインポートしますが、child
とparent
の読み込みが完了するまで、parent
のオブジェクトをchild
から遅延させることです。特に、child
のモジュールレベルコードでfrom parent import something
を使用する代わりに、import parent
を使用し、の関数またはメソッドコードの中からparent.something
にアクセスする必要があります。 child
とparent
の実行が終了するまで、これらの関数とメソッドは実行されないため、parent
モジュールのすべての要素が正しく定義されるため、これは安全です。
ここでは、コメントで説明した設定を使用して、私が意味するものの一例を示します。あなたに問題をもたらしているコードについてより多くの情報を提供すれば、私はこれをもっと細かく調整することができます。
バージョン1(動作しません)
__main__.py:
from user import User
u = User()
user.py:
from data_manager import DataManager
...
class User:
def __init__(self, data_manager=None):
if data_manager is None:
data_manager = DataManager(user=self)
self.data_manager = data_manager
data_manager。PY:
# next line will fail because user.py has been partly loaded
# and user.User doesn't exist yet
from user import User
...
class DataManager:
def __init__(self, user=None):
...
if user is None:
user = User(data_manager=self)
self.user = user
バージョン2は、(動作する)
__main__.py:
from user import User
u = User()
user.py:
import data_manager as dm
...
class User:
def __init__(self, data_manager=None):
if data_manager is None:
data_manager = dm.DataManager(user=self)
self.data_manager = data_manager
data_manager.py:
import user as user_module
...
# this defines a class which will eventually create an instance
# of user.User, but it won't try to do that until control returns
# to __main__.py, by which point the `user` and `data_manager`
# modules are fully defined
class DataManager:
def __init__(self, user=None):
...
if user is None:
user = user_module.User(data_manager=self)
self.user = user
クラスの__init__
メソッドの参照は、クラスが実際にインスタンス化されるまで解決されないことに注意してください。つまり、user = user_module.User(data_manager=self)
行は次のようになります。「現在のモジュールでuser_module
というオブジェクトを探し、そのオブジェクト内でUser
属性を調べ、そのクラスのオブジェクトを作成します。重要なことは、data_manager
は、user
モジュールを早期に安全にインポートできることです(モジュールはすでに一部分のみ構成されていますが、既に存在しています)。DataManager
オブジェクトがインスタンス化されるまで、上記のコードはuser
モジュール内で実際に何も検索しませんこれにより、時間はuser.User
が適切に定義されます。
最初に巡回関係がある理由は何ですか? – deceze
両方のモジュールに必要なものがある場合は、それを別のモジュールに入れます。 –
[Pythonで循環インポートを避けるにはどうすればいいですか?](http://stackoverflow.com/questions/7336802/how-to-avoid-circular-imports-in-python) –