web-dev-qa-db-ja.com

Pythonインポートは正確に機能しますか?

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を返しますか?

49
corazza

パート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ドキュメンテーションは非常に優れており、通常は冗長です-そこにある可能性のあるほとんどすべての言語関連の質問に対する答えが見つかります。ここにいくつかの便利なリンクがあります。

60
ThiefMaster

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

いいえ、pythonは 'imported'を2回取得しません。pythonモジュールをロードすると、 sys.modulesでモジュールをチェックします 。そこになければ、そこに置かれ、ロードされます。

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

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

多少関連するトピックでは、from camelot import *の実行は 通常のインポートとは異なります です。

3
Casey Kuball