私はPython=を学習しており、まだ1年ほど勉強していますが、まだ初心者です。メインモジュール内で呼び出される関数のモジュールを記述しようとしています。それぞれ呼び出されたモジュールの関数を実行するには数学モジュールが必要です。呼び出されたモジュール内に数学モジュールをインポートせずにこれを行う方法があるかどうか疑問に思っています。
main.py
:
from math import *
import module1
def wow():
print pi
wow()
module1.cool()
module1.py
:
def cool():
print pi
main.py
を実行すると、次のようになります。
3.14159265359
Traceback (most recent call last):
File "Z:\Python\main.py", line 10, in <module>
module1.cool()
File "Z:\Python\module1.py", line 3, in cool
print pi
NameError: global name 'pi' is not defined
main.py
の実行時に名前エラーが発生するのはなぜですか。 pi
が変数にアクセスできるため、変数wow
はインポート時にメインモジュールに対してグローバルになることを知っています。また、module1.cool
を出力して<function cool at 0x02B11AF0>
を取得できるため、cool
がインポート時にメインモジュールに対してグローバルになることも知っています。したがって、cool
はメインモジュールのグローバルネームスペース内にあるので、プログラムは最初に関数cool
内で変数pi
を探し、次に、そうでない場合はtそこにそれを見つけて、main
モジュールの内部で変数pi
を探し、それを見つけるがありますか?
これを回避する唯一の方法は、数学モジュールをmodule1.py
内にインポートすることです。私はそれの考えが好きではありません、なぜならそれは物事をより複雑にし、私はニースで単純なコードのファンだからです。名前空間の把握に近づいているような気がしますが、これについては助けが必要です。ありがとう。
トレースバックが示すように、問題はmain.py
ではなくmodule1.py
にあります。
Traceback (most recent call last):
File "Z:\Python\main.py", line 10, in <module>
module1.cool()
File "Z:\Python\module1.py", line 3, in cool
print pi
NameError: global name 'pi' is not defined
つまり、in module1
はインポートされていないため、グローバル名pi
はありません。 from math import *
でmain.py
を実行すると、すべてがmath
モジュールの名前空間からmain
モジュールの名前空間にインポートされ、everyモジュールの名前空間にはインポートされません。
ここで欠落している重要な点は、各モジュールに独自の「グローバル」名前空間があるということです。 Cなどの言語では、すべてのextern
変数と関数で共有される単一のグローバル名前空間があるため、これは最初は少し混乱する可能性があります。しかし、その仮定を通過すると、Pythonの方法は完全に理にかなっています。
したがって、module1
のpi
を使用する場合は、from math import *
でmodule1.py
を実行する必要があります。 (または、他の方法で注入することもできます。たとえば、module1.py
はfrom main import *
を実行でき、main.py
はmodule1.pi = pi
を実行できます。または、pi
を魔法のbuiltins
/__builtin__
モジュール、またはその他のさまざまなトリックを使用します。ただし、明らかな解決策は、インポートする場所でimport
を実行することです。)
補足として、通常、対話型インタープリターや、場合によってはトップレベルのスクリプトを除いて、from foo import *
を実行することは望ましくありません。例外があります(たとえば、いくつかのモジュールはそのように使用するように明示的に設計されています)。ただし、経験則ではimport foo
または制限付きfrom foo import bar, baz
を使用します。
「明示的は暗黙的より良い」は、Python(launch python and run _import this
_))の作成者が行った設計上の決定です。
したがって、module1.cool()
を実行すると、Pythonはpi
モジュールで未定義のmain
を検索しません。
数式モジュールを使用するときはいつでも明示的にインポートする必要があります-これがPythonの動作方法です。
また、_from X import *
_スタイルのインポートは避けてください。これも悪い習慣です。ここでは、次のことができます:_from math import pi
_。
@abarnertのコメントで言及されているexec
(python 3)またはexecfile
(python 2)の単純なアプローチは、一部のワークフローで役立つ場合があります。必要なのは、インポート行を次のものに置き換えるだけです。
exec( open("module1.py").read() ) # python 3
次に、cool()
ではなくmodule1.cool()
を使用して関数を呼び出すだけです。 cool()
内では、OPが当初期待していたように、変数pi
はグローバルのように動作します。
簡単に言うと、これは、メインプログラムの上部に表示され、長所と短所の両方がある関数定義を単に隠すことです。複数のモジュールとインポートを含む大規模なプロジェクトでは、適切な名前空間の代わりにexec
を使用するのはおそらく間違いです。これは、単一のグローバル名前空間内にあまり多くのものを保持したくないためです。
ただし、単純なケース(シェルスクリプトとしてPythonを使用する場合など)の場合、exec
を使用すると、グローバル名前空間を共有しながら共有関数を非表示にする簡単で簡潔な方法が得られます。この場合、関数の名前の付け方をさらに検討する必要があります(たとえば、v1_cool
とv2_cool
を実行できないため、v1.cool
とv2.cool
を使用して、異なるバージョンを追跡します)。
ここでexec
を使用することの明らかでない欠点の1つは、これを回避することはできますが、実行されたコードのエラーがエラーの行番号を表示しない可能性があることです。 エラーの行番号を取得する方法execまたはPythonのexecfile
他の人が言ったように、実際にはmodule1
にグローバルpi
はありません。 pi
からmath
を1回だけインポートし、explicitlyをインポートするのが適切な解決策は、取得しているpi
がmodule1
から:
main.py
:
import module1
def wow():
print module1.pi
wow()
module1.cool()
module1.py
:
from math import pi
def cool():
print pi
モジュール内では、単にfrom math import pi
、これはpiを数学からインポートするだけで、数学モジュール全体はインポートしません。