Pythonでインポートがどのように機能するか理解できない2つの特定の状況があります。
最初の特定の状況:
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を返しますか?
パート1
モジュールは一度だけロードされるため、再度インポートしてもパフォーマンスの低下はありません。実際に再度ロード/解析する場合は、reload()
モジュールを使用する必要があります。
最初にチェックされる場所は_
sys.modules
_です。これは、以前にインポートされたすべてのモジュールのキャッシュです。 [ ソース ]
パート2
_from foo import *
_は、a
をローカルスコープにインポートします。 a
に値を割り当てると、新しい値に置き換えられますが、元の_foo.a
_変数は変更されません。
したがって、_import foo
_を変更して_foo.a
_を変更しない限り、両方の呼び出しは同じ値を返します。
リストや辞書などの可変型の場合、それは変更されますが、実際に変更すると元の変数に影響しますが、新しい値を割り当てても_foo.whatever
_は変更されません。
より詳細な情報が必要な場合は、 http://docs.python.org/reference/executionmodel.html をご覧ください。
次の構成要素は名前をバインドします:関数への仮パラメータ、importステートメント、クラスおよび関数定義(これらは定義ブロック内のクラスまたは関数名をバインドします)、および割り当て、forループヘッダー、except句ヘッダーの2番目の位置、またはwithステートメント内で発生した場合の識別子であるターゲット。
2つの太字のセクションは、関連するセクションです。まず、名前a
は、インポート中に_foo.a
_の値にバインドされます。次に、_a = 5
_を実行すると、名前a
が_5
_にバインドされます。リスト/ dictを変更してもバインディングは発生しないため、これらの操作では元のバインディングが変更されます(b
および_foo.b
_は操作する同じオブジェクトにバインドされます)。新しいオブジェクトをb
に割り当てると、再びバインド操作になるため、b
を_foo.b
_から分離します。
また、import
ステートメントが正確に何をするのかに注意する価値があります。
import foo
_は、モジュール名を現在のスコープ内のモジュールオブジェクトにバインドします。したがって、_foo.whatever
_を変更すると、そのモジュール内の名前が使用されます。変更/割り当ては、モジュール内の変数に影響します。from foo import bar
_は、指定された名前のみをfoo
の同じ名前の要素にバインドします(つまり、foo
はバインドされないままになります)。したがって、bar
の操作は前述のように動作します。from foo import *
_は前のものと同様に動作しますが、アンダースコアが前に付かないすべてのグローバル名をインポートします。モジュールが___all__
_を定義している場合、このシーケンス内の名前のみがインポートされます。パート3(あなたの質問にも存在しません:p)
pythonドキュメンテーションは非常に優れており、通常は冗長です-そこにある可能性のあるほとんどすべての言語関連の質問に対する答えが見つかります。ここにいくつかの便利なリンクがあります。
import
、yield
などのステートメント)for
、try
、with
などのブロックステートメント)最初の質問に答えるには:
いいえ、pythonは 'imported'を2回取得しません。pythonモジュールをロードすると、 sys.modules
でモジュールをチェックします 。そこになければ、そこに置かれ、ロードされます。
2番目の質問に答えるには:
モジュールは、from camelot import *
シナリオにエクスポートする名前を定義できます。動作は、既存の変数を参照するのではなく、既存の値の名前を作成することです(Pythonには参照がありません)。
多少関連するトピックでは、from camelot import *
の実行は 通常のインポートとは異なります です。