61

Python でインポートがどのように機能するか理解できない特定の状況が 2 つあります。

1 つ目の特定の状況:

2 つの異なる Python スクリプトで同じモジュールをインポートすると、モジュールが 2 回インポートされませんよね? Python が最初に遭遇したときはインポートされ、2 回目はモジュールがインポートされているかどうかを確認しますか、それともコピーを作成しますか?

2 番目の特定の状況:

と呼ばれる次のモジュールを考えてみましょうbla.py:

a = 10

そして、foo.pyインポートするモジュールがありますbla.py

from bla import *

def Stuff ():
    return a

その後bar.py、ユーザーによって実行される というスクリプトがあります。

from foo import *
Stuff() #This should return 10 
a = 5
Stuff()

ここで私は知りません: Stuff()10 または 5 を返しますか?

4

2 に答える 2

73

パート1

モジュールは 1 回だけロードされるため、再度インポートしてもパフォーマンスが低下することはありません。実際に再度ロード/解析したい場合はreload()、モジュールを使用する必要があります。

最初にチェックされるのはsys.modules、以前にインポートされたすべてのモジュールのキャッシュです。[ソース]


パート2

from foo import *aローカル スコープにインポートします。に値を代入するaと、新しい値に置き換えられますが、元のfoo.a変数は変更されません。

したがってimport foo、変更しない限りfoo.a、両方の呼び出しで同じ値が返されます。

list や dict などの変更可能な型の場合は異なり、変更すると元の変数に実際に影響しますが、新しい値を割り当てても変更されませんfoo.whatever

より詳細な情報が必要な場合は、http://docs.python.org/reference/executionmodel.htmlをご覧ください。

次の構造体は名前をバインドします: 関数への正式なパラメーター、インポート ステートメント、クラスおよび関数定義 (これらは、定義ブロックでクラスまたは関数名をバインドします)、および代入で発生する場合は識別子であるターゲット、for ループ ヘッダー、2 番目のwith ステートメントの場合と同様に、except 句のヘッダーまたはその後の位置。

2 つの太字のセクションは、関連するセクションです。最初に、インポート中に名前aが の値にバインドされます。foo.a次に、 を実行するa = 5と、名前aが にバインドされ5ます。リスト/辞書を変更してもバインディングは発生しないため、これらの操作は元の操作を変更します (bそしてfoo.b、操作対象と同じオブジェクトにバインドされます)。新しいオブジェクトを に割り当てるbことは、再びバインド操作になるため、 とは別のものになりbますfoo.b

importステートメントが正確に何をするかにも注目する価値があります。

  • import fooモジュール名を現在のスコープ内のモジュール オブジェクトにバインドするため、 を変更するfoo.whateverと、そのモジュール内の名前で作業できます。変更や割り当ては、モジュール内の変数に影響します。
  • from foo import barfoo指定された名前のみを同じ名前の要素にバインドします(つまり、バインドされないままになります)。fooそのため、操作barは前述のように動作します。
  • from foo import *前のものと同じように動作しますが、アンダースコアが前に付いていないすべてのグローバル名をインポートします。__all__モジュールがこのシーケンス内の名前のみを定義する場合、インポートされます。

パート3(あなたの質問には存在しません:p)

Python のドキュメントは非常に優れており、通常は詳細です。そこには、考えられる言語関連のほぼすべての質問に対する回答があります。便利なリンクを次に示します。

于 2012-05-08T15:33:01.403 に答える
3

最初の質問に答えるには:

いいえ、python は 2 回「インポート」されません。python がモジュールをロードするとき、モジュールを でチェックしますsys.modules。そこにない場合は、そこに入れられ、ロードされます。

2 番目の質問に答えるには:

モジュールは、シナリオにエクスポートする名前を定義できますfrom camelot import *。動作は、既存の変数を参照するのではなく、既存の値の名前を作成することです (python には参照がありません)。

少し関連するトピックでは、 a を実行することは、通常の import と同じfrom camelot import *ではありません。

于 2012-05-08T15:46:29.900 に答える