14

それを知って驚いた

import foo

from foo import *

グローバルメンバーにさまざまな影響を与えました。私の実験が正しい動作であることを確認したかったのです。

最初の例では、モジュール foo のメンバーを変更すると、foo をインポートするすべてのコードに反映されます。ただし、後者の場合にそのメンバーを変更すると、インポートされたファイルにのみ影響するようです。つまり、後者のアプローチを使用すると、各インポート ファイルに foo からのメンバーの独自のコピーが与えられます。

私が望む動作は、すべてのファイルから foo.x にアクセスし、すべてのファイルからそれを変更し、その変更をすべてのファイルに反映させることです (必要に応じて真のグローバル)。

4

2 に答える 2

16

はい、あなたの観察は正しいです。これは、バインディングが Python で機能する方法の結果です。

するとき

import foo

fooは、モジュールを参照するグローバル名になりますfoo。するとき

foo.bar = 7

次に、参照が追跡され、オブジェクトfooがロードされます。その後7、属性に格納されbarます。

別のモジュールが をインポートfooすると、オブジェクトが取り出されsys.modules['foo']、変更された値が取得されます。

するとき

from foo import bar

globals()['bar']参照に設定されていますfoo.bar。後で行うとき

 bar = 7

globals()['bar']はもはや参照していませんfoo.barが、 のコピーを参照しています7。つまり、インポート モジュールのグローバル スコープ内の元のバインディングは単純に置き換えられます。

最初の例では、格納されているオブジェクトの属性を変更してsys.modulesおり、それをインポートしたすべてのモジュールに共通です。2 番目の例では、インポート モジュールのグローバル スコープを変更しています。

の線に沿って何かをする場合

 from foo import fobaz
 fobaz.foobar = 7

次に、グローバル参照を上書きするのではなく、それに従って、それが指すオブジェクトの属性を変更するため、その変更他のインポートモジュールに伝播されます。基本的に、グローバルバインディングを上書きしない限り、変更可能なオブジェクトを変更できるはずです。

このようなものは、Pythonで真のグローバルにきれいに到達できる最も近いものだと思います。言語として、名前空間を非常に重視しています。

于 2010-12-14T07:11:49.603 に答える
4

グローバル変数は一般的に悪いことだと考えられていることを考えると、「真のグローバル」変数は非常に悪いことだと思います。

同様の動作を得るもう 1 つの方法は、シングルトン オブジェクトでクラス スコープの属性を使用し、それをインポートすることです。次に、「グローバル」変数をどこから取得しているかが明確になります。

于 2010-12-14T06:18:01.530 に答える