18
>>> import math
>>> math.pi
3.141592653589793
>>> math.pi = 3
>>> math.pi
3
>>> import math
>>> math.pi
3

最初の質問: なぜmath.pi戻れないのですか?

import定義されたすべての変数と関数を現在のスコープにインポートすると思いました。また、変数名が現在のスコープに既に存在する場合は、それが置き換えられます。

はい、それはそれを置き換えます:

>>> pi = 3
>>> from math import *
>>> pi
3.141592653589793

次に、インポートさ math.pi = 3れたプロパティが割り当てによって実際に変更された可能性があると思いましたmath class(またはそれmath moduleですか?) 。import math

私が正しかった:

>>> import math
>>> math.pi
3.141592653589793
>>> math.pi = 3
>>> from math import *
>>> pi
3

したがって、次のようになり
ます。そうすると、クラスのようなものとしてimport xインポートされます。xx.property に変更を加えた場合、その変更はモジュールに保持されるため、再度インポートするたびに変更されたバージョンになります。

本当の質問:

  1. なぜimportこのように実装されているのですか?すべてimport mathのインポートで の新しい未変更のコピーを許可しないのはなぜmathですか? インポートさmathれたものを変更できるようにしておくのはなぜですか?
  2. math.pi実行後に戻るための回避策はありますかmath.pi = 3(もちろん、を除くmath.pi = 3.141592653589793)?
  3. もともと私import mathはよりも好ましいと思っていましたfrom math import *。しかし、この動作により、この方法でインポートしたモジュールを他の誰かが変更している可能性があるのではないかと心配になります...どうすればよいimportですか?
4

3 に答える 3

13

Python は、特定のモジュールのコピーを 1 つだけ作成します。モジュールを繰り返しインポートすると、元のモジュールが再利用されます。これは、モジュール A と B が C と D をインポートし、モジュールが E と F をインポートした場合などに、C と D が 2 回ロードされ、E と F が 4 回ロードされるなどの理由によるものです。メモリが不足する前に冗長モジュールをロードするのに数分かかります。また、A が B をインポートし、B が A をインポートした場合、再帰ループに陥り、何の役にも立たずにメモリ不足になります。

解決策:他のモジュールの内容を台無しにしないでください。もしそうなら、それはインタプリタ全体の変更です。これを行いたい状況がときどきあるので、Python はそれを可能にしますが、通常は悪い考えです。

于 2013-09-18T03:56:19.487 に答える
10

モジュールは何度もインポートできます。importステートメントは から参照をロードするだけですsys.modules。ステートメントがモジュールをディスクから再ロードする場合importも、非常に遅くなります。このようなモジュールの変更は非常にまれであり、文書化されたまれな状況でのみ行われるため、心配する必要はありません。

モジュールをリロードする方法:

>>> import imp
>>> imp.reload(math)
<module 'math' (built-in)>
>>> math.pi
3.141592653589793
于 2013-09-18T03:50:55.943 に答える
6

インポート動作は、モジュールが状態を持つことを可能にすることを目的としています。たとえば、初期化コードを実行するモジュールは、初期化時に何が起こるかに基づいて、あらゆる種類の異なる動作をする可能性があります (良い例は os モジュールで、OS に応じて異なるバージョンのパス サブモジュールを透過的にロードします)。 . 初期化を何度も再実行することなく、多くの異なるコードがモジュールにアクセスできるようにするための通常の動作が存在します。さらに、モジュールは他の言語の静的クラスのように機能します。モジュールは状態を維持でき、グローバル変数の代わりとしてよく使用されます。たとえば、locale モジュールを使用してローカル カルチャ変数 (通貨形式など) を設定することができます。コードの一部のlocale.setlocaleとlocal.getlocalein another は、グローバル変数を作成するための優れた代替手段です。

もちろん、あなたの例は弱点を指摘しています。古典的なpythonの原則の1つは

ここではみんな大人です

この言語は、作成者がモジュールまたはクラスのコンテンツをロックダウンできるようにする、たとえば Java や C# に見られるプライバシー管理機能の多くを提供しません。悪意を感じている (または単に自殺したい) 場合は、例で行ったのとまったく同じことを行うことができます: pi を 3 に変更するか、関数を変数に変更するか、その他のあらゆる種類の厄介なことを行います。この言語は、それを難し​​くするようには設計されていません。責任を負うのはコーダー次第です。

@Josh Leeの回答は、リロードの使用方法を示しています。これは、モジュールをディスクベースの状態にリフレッシュする正しい方法です。リロードを使用する知恵は、主にモジュール内の初期化コードの量と、問題のモジュールによってインポートまたはインポートされる他のモジュールの Web に依存します。

于 2013-09-18T04:02:54.067 に答える