回答:
私はこのソリューションを形や形で保証するものではありません。ただし、__builtin__
モジュールに変数を追加__builtin__
すると、デフォルトでは、それを含む他のモジュールのグローバルであるかのようにアクセスできます。
a.pyには
print foo
b.pyには
import __builtin__
__builtin__.foo = 1
import a
その結果、「1」が出力されます。
編集:__builtin__
モジュールはローカルシンボルとして利用可能である__builtins__
-これらの答えの二つの間の不一致の理由です。また、python3 __builtin__
ではに名前が変更さbuiltins
れています。
hasattr(__builtin__, "foo")
。
グローバルなクロスモジュール変数が必要な場合は、単純なグローバルモジュールレベルの変数で十分な場合があります。
a.py:
var = 1
b.py:
import a
print a.var
import c
print a.var
c.py:
import a
a.var = 2
テスト:
$ python b.py
# -> 1 2
実際の例:Djangoのglobal_settings.py(ただし、Djangoアプリではオブジェクトの インポートによって設定が使用されますdjango.conf.settings
)。
a.py
)に含まれている場合はmain()
どうなりますか?それは重要ですか?
if __name__=="__main__"
ガードでガードを使用して、インポート時に予期しないコードが実行されるのを防ぎます。
id()
身元を確認する)
それが意味をなす多くの状況があり、いくつかの(密に結合された)モジュール間で既知のいくつかのグローバルを持つようにプログラミングを単純化すると私は信じています。この精神の中で、それらを参照する必要のあるモジュールによってインポートされるグローバルのモジュールを持つというアイデアについて少し詳しく説明したいと思います。
そのようなモジュールが1つしかない場合は、「g」という名前を付けます。その中で、グローバルとして扱う予定のすべての変数にデフォルト値を割り当てます。それらのいずれかを使用する各モジュールでは、「from g import var」を使用しません。これは、インポート時にのみgから初期化されるローカル変数のみが生成されるためです。ほとんどの参照はg.varの形式で行い、「g」を使用します。他のモジュールからアクセスできる可能性のある変数を扱っていることを常に思い出させてくれます。
このようなグローバル変数の値がモジュール内の関数で頻繁に使用される場合、その関数はローカルコピーを作成できます:var = g.var。ただし、varへの割り当てはローカルであり、グローバルg.varは割り当てでg.varを明示的に参照しないと更新できないことを理解することが重要です。
モジュールのさまざまなサブセットによって共有されるそのような複数のグローバルモジュールを使用して、状況をもう少し厳しく制御することもできます。私のグローバルモジュールに短い名前を使用する理由は、それらの出現によってコードが乱雑になりすぎないようにするためです。ほんの少しの経験で、彼らはたった1つか2つのキャラクターで十分ニーモニックになります。
たとえば、xがgでまだ定義されていない場合でもgxへの割り当てを行うことは可能であり、別のモジュールがgxにアクセスできます。それ。割り当ての変数名のタイプミスの結果として、誤ってgに新しい変数を作成する可能性があります。dir(g)の調査は、そのような事故によって生じた可能性のある驚きの名前を見つけるのに役立つことがあります。
1つのモジュールのグローバルを別のモジュールに渡すことができます。
モジュールA:
import module_b
my_var=2
module_b.do_something_with_my_globals(globals())
print my_var
モジュールB:
def do_something_with_my_globals(glob): # glob is simply a dict.
glob["my_var"]=3
グローバル変数は通常悪い考えですが、次のように割り当てることでこれを行うことができます__builtins__
:
__builtins__.foo = 'something'
print foo
また、モジュール自体は、任意のモジュールからアクセスできる変数です。だからと呼ばれるモジュールを定義した場合my_globals.py
:
# my_globals.py
foo = 'something'
次に、それをどこからでも使用できます。
import my_globals
print my_globals.foo
変更するので__builtins__
はなくモジュールを使用する方が、この種のグローバルを実行するためのよりクリーンな方法です。
これは、モジュールレベルの変数ですでに実行できます。モジュールは、インポート元のモジュールに関係なく同じです。したがって、変数を、それを配置する意味のある任意のモジュールでモジュールレベルの変数にして、他のモジュールからアクセスまたは割り当てることができます。変数の値を設定するために関数を呼び出すか、またはいくつかのシングルトンオブジェクトのプロパティにすることをお勧めします。そうすれば、変数が変更されたときにコードを実行する必要が生じた場合でも、モジュールの外部インターフェイスを壊すことなく実行できます。
これは通常、物事を行うための優れた方法ではありません—グローバルを使用することはめったにありません—が、これが最もクリーンな方法だと思います。
変数が見つからない場合があるとの回答を投稿したいと思いました。
循環インポートはモジュールの動作を壊す可能性があります。
例えば:
first.py
import second
var = 1
second.py
import first
print(first.var) # will throw an error because the order of execution happens before var gets declared.
main.py
import first
これは例ですが、明らかなはずですが、大規模なコードベースでは、これは本当に混乱する可能性があります。
これは、__builtin__
名前空間を変更するように聞こえます。それをするために:
import __builtin__
__builtin__.foo = 'some-value'
__builtins__
直接使用しないでください(追加の「s」に注意してください)-明らかにこれは辞書またはモジュールの可能性があります。これを指摘してくれたΤΖΩΤΖΙΟΥのおかげで、もっと多くがここにあります。
今、foo
どこでも使用可能です。
これを一般的に行うことはお勧めしませんが、これを使用するかどうかはプログラマ次第です。
これへの割り当ては上記のように行う必要がありfoo = 'some-other-value'
ます。設定すると、現在のネームスペースにのみ設定されます。
私は、これが本当に欠けていると感じたいくつかの組み込みのプリミティブ関数に使用します。1つの例は、filter、map、reduceと同じ使用法セマンティクスを持つfind関数です。
def builtin_find(f, x, d=None):
for i in x:
if f(i):
return i
return d
import __builtin__
__builtin__.find = builtin_find
これを実行すると(たとえば、エントリポイントの近くにインポートすることにより)、すべてのモジュールでfind()を使用できるようになります。
find(lambda i: i < 0, [1, 3, 0, -5, -10]) # Yields -5, the first negative.
注:もちろん、これを行うには、フィルターと別のラインを使用して長さがゼロかどうかをテストするか、ある種の奇妙なラインを縮小しますが、いつも変だと感じていました。
辞書を使用して、モジュール間で変更可能な(または変更可能な)変数を実現できます。
# in myapp.__init__
Timeouts = {} # cross-modules global mutable variables for testing purpose
Timeouts['WAIT_APP_UP_IN_SECONDS'] = 60
# in myapp.mod1
from myapp import Timeouts
def wait_app_up(project_name, port):
# wait for app until Timeouts['WAIT_APP_UP_IN_SECONDS']
# ...
# in myapp.test.test_mod1
from myapp import Timeouts
def test_wait_app_up_fail(self):
timeout_bak = Timeouts['WAIT_APP_UP_IN_SECONDS']
Timeouts['WAIT_APP_UP_IN_SECONDS'] = 3
with self.assertRaises(hlp.TimeoutException) as cm:
wait_app_up(PROJECT_NAME, PROJECT_PORT)
self.assertEqual("Timeout while waiting for App to start", str(cm.exception))
Timeouts['WAIT_JENKINS_UP_TIMEOUT_IN_SECONDS'] = timeout_bak
の起動test_wait_app_up_fail
時の実際のタイムアウト時間は3秒です。
変数の値を渡すためにグローバル/モジュール名前空間ではなくクラス名前空間を使用することにより、グローバル変数(http://wiki.c2.com/?GlobalVariablesAreBadを参照)を使用することのいくつかの欠点を回避できるか。次のコードは、2つの方法が基本的に同じであることを示しています。以下で説明するように、クラス名前空間の使用には若干の利点があります。
次のコードフラグメントは、グローバルまたはモジュールの名前空間とクラスの名前空間の両方で、属性または変数が動的に作成および削除されることも示しています。
wall.py
# Note no definition of global variables
class router:
""" Empty class """
変数を跳ね返すために使用されるので、このモジュールを「壁」と呼びます。これは、空のクラス「ルーター」のグローバル変数とクラス全体の属性を一時的に定義するスペースとして機能します。
source.py
import wall
def sourcefn():
msg = 'Hello world!'
wall.msg = msg
wall.router.msg = msg
このモジュールは、壁をインポートsourcefn
し、メッセージを定義し、1つはグローバル経由で、もう1つはルーター機能経由で、2つの異なるメカニズムでメッセージを送信する単一の関数を定義します。変数wall.msg
とwall.router.message
は、それぞれの名前空間で初めてここで定義されることに注意してください。
dest.py
import wall
def destfn():
if hasattr(wall, 'msg'):
print 'global: ' + wall.msg
del wall.msg
else:
print 'global: ' + 'no message'
if hasattr(wall.router, 'msg'):
print 'router: ' + wall.router.msg
del wall.router.msg
else:
print 'router: ' + 'no message'
このモジュールはdestfn
、2つの異なるメカニズムを使用して、ソースから送信されたメッセージを受信する関数を定義します。変数「msg」が存在しない可能性があります。destfn
表示された変数も削除します。
main.py
import source, dest
source.sourcefn()
dest.destfn() # variables deleted after this call
dest.destfn()
このモジュールは、以前に定義された関数を順番に呼び出します。dest.destfn
変数への最初の呼び出しの後、存在wall.msg
しwall.router.msg
なくなりました。
プログラムからの出力は次のとおりです。
global:Hello world!
ルーター:こんにちは!
グローバル:メッセージ
ルーターなし:メッセージなし
上記のコードフラグメントは、モジュール/グローバルとクラス/クラス変数のメカニズムが本質的に同一であることを示しています。
多数の変数を共有する場合、名前空間の汚染は、wall1、wall2などの複数の壁タイプのモジュールを使用するか、1つのファイルで複数のルータータイプクラスを定義することによって管理できます。後者はやや整然としているため、クラス変数メカニズムを使用するためのわずかな利点になる可能性があります。