2015-11-13 10 views
7

のは、a.pyが可能てみましょう:"import module"と "from module import *"のグローバル変数に関して動作が異なるのはなぜですか?

def foo(): 
    global spam 
    spam = 42 
    return 'this' 

コンソールで、私だけでimport a場合、物事は私には意味をなさない:しかし

>>> import a 
>>> a.foo() 
'this' 
>>> a.spam 
42 

、私はあまり人気ことを行う場合...

>>> from a import * 
>>> foo() 
'this' 
>>> spam 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
NameError: name 'spam' is not defined 
>>> a.spam 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
NameError: name 'a' is not defined 

名前空間が「from module import *」のように人々が好きではないとの意見を読んだしかし、私はこの行動について何も見つけることができず、率直に言って、これが私が偶然に起こした問題であることを理解しました。

+2

'a.py'で定義された' globals'はそのモジュール自体でグローバルになるので、インポートするグローバル変数は定義しません。 'foo .__ globals__'をチェックしてください。 –

+0

[各モジュールには独自のプライベートシンボルテーブルがあり、モジュールで定義されているすべての関数でグローバルシンボルテーブルとして使用されます...](https://docs.python.org/3/tutorial/modules.html#more -on-modules) –

答えて

9

a.spamを要求すると、モジュールaspamに名前空間の検索が行われます。しかし、あなただけのspamを求めるとき:

>>> from a import * # imported foo, spam doesn't exist yet 
>>> foo() 

spamをではなく、現在のモジュールでは、名前空間(あなたがが、このような輸入とそれにアクセスすることはできません)で作成されます。そして、aの新しく追加されたグローバルを、*にインポートされたすべての名前空間モジュールaに追加することを約束したような人はいません。それはインタプリタの内部にインポートリンクを格納する必要があり、ひどく読み込まれたモジュールがそのようなトリックをしていると、パフォーマンスが低下する可能性があります。

foo()を呼び出す前に、メインモジュールにspamを定義したとします。それは完全に名前の衝突でしょう。私は、一般的にVovanrock2002に同意

from a import * 
print(foo()) 
from a import * 
print(spam) 
+0

これは私が理解するのに十分明確です、ありがとうございます。 –

1

だけ説明として、あなたはモジュールa新鮮なアップデートを入手するためにfrom a import *を行うことができます。

私に最近説明したように、 '。'スコープ解決演算子です。 import afrom a import *には異なる構文があります。 from a import *は、各グローバル変数をaから別々にインポートし、それらをローカルスコープの変数としてバインドします。より具体的な例としては、import datetimefrom datetime import dateの違いが考えられます。前者では、datetime.date(2015, 11, 12)を使って日付オブジェクトを作成しなければならず、後者ではdate(2015, 11, 12)を使用するだけです。

あなたが私はあなたとは異なるする必要がありますimport statement

の詳細を読むことができます、しかし、その中で私はスパムが人生、宇宙、すべてのものとの意味であると信じていません。

+1

2番目のケースでは、_or_ a.spamというスパムを呼び出せません。スパムが本当に答えがあれば、世界は悲しいところです。 –

2

のステップで徹底してステップを行ってみましょう:

aだけの機能を参照するシンボルfooがあり、輸入の時点で。

機能が実行された場合のみ、aは追加シンボルspamを取得します。

最初のケースでは、import aを実行してモジュールに「ハンドル」を取得し、後で何が起こるかを監視することができます。 a.foo()を呼び出す前にa.spamを実行すると、エラーが発生します。第2のケースで

from a import *が現在がモジュールにあるものは何でも与えます - それはちょうど spam()です。それを呼び出した後、 from a import *を実行して spamを取得することもできます。

関連する問題