この__debug__
変数は、すべてのモジュールに影響するため、便利です。同じように機能する別の変数を作成したい場合、どうすればよいですか?
あるモジュールで foo を変更すると、他のモジュールで更新されるという意味で、変数 (オリジナルで 'foo' と呼びましょう) は真にグローバルである必要はありません。他のモジュールをインポートする前に 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
)。
私は、この解決策を形や形を問わず支持しません。しかし、モジュールに変数を追加すると、デフォルトでそれらすべてを__builtin__
含む他のモジュールからのグローバルであるかのようにアクセスできます。__builtin__
a.py を含む
print foo
b.py を含む
import __builtin__
__builtin__.foo = 1
import a
その結果、「1」が出力されます。
編集:__builtin__
モジュールはローカル シンボルとして使用できます。これ__builtins__
が、これらの回答のうち 2 つが一致しない理由です。また、python3 で__builtin__
名前が に変更されたことにも注意してください。builtins
それが理にかなっている状況はたくさんあり、いくつかの (密結合された) モジュール間で認識されるいくつかのグローバルを持つことでプログラミングが簡素化されると私は信じています。この精神で、グローバルを参照する必要があるモジュールによってインポートされるグローバルのモジュールを持つという考えについて少し詳しく説明したいと思います。
そのようなモジュールが 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) の調査は、そのような偶然によって生じたかもしれない驚きの名前を発見するのに役立つ場合があります。
モジュールを定義し (それを "globalbaz" と呼びます)、その中に変数を定義します。この「疑似グローバル」を使用するすべてのモジュールは、「globalbaz」モジュールをインポートし、「globalbaz.var_name」を使用して参照する必要があります。
これは、変更の場所に関係なく機能します。インポートの前または後に変数を変更できます。インポートされたモジュールは最新の値を使用します。(おもちゃの例でこれをテストしました)
明確にするために、globalbaz.py は次のようになります。
var_name = "my_useful_string"
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
秒.py
import first
print(first.var) # will throw an error because the order of execution happens before var gets declared.
main.py
import first
この例では明らかですが、大規模なコードベースでは、これは非常に混乱を招く可能性があります。
変数の値を渡すためにグローバル/モジュール名前空間ではなくクラス名前空間を使用することで、グローバル変数を使用することの欠点のいくつかを回避できるかどうか疑問に思いました (例: http://wiki.c2.com/?GlobalVariablesAreBadを参照)。 . 次のコードは、2 つのメソッドが本質的に同一であることを示しています。以下で説明するように、クラスの名前空間を使用することにはわずかな利点があります。
次のコード フラグメントは、グローバル/モジュール名前空間とクラス名前空間の両方で、属性または変数を動的に作成および削除できることも示しています。
wall.py
# Note no definition of global variables
class router:
""" Empty class """
私はこのモジュールを「壁」と呼んでいます。これは、変数を跳ね返すために使用されるためです。空のクラス「ルーター」のグローバル変数とクラス全体の属性を一時的に定義するスペースとして機能します。
ソース.py
import wall
def sourcefn():
msg = 'Hello world!'
wall.msg = msg
wall.router.msg = msg
このモジュールは wall をインポートし、メッセージを定義する単一の関数sourcefn
を定義し、2 つの異なるメカニズム (1 つはグローバル経由、もう 1 つはルーター機能経由) によってメッセージを発行します。変数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
なくなります。
プログラムからの出力は次のとおりです。
グローバル: ハローワールド!
ルーター: ハローワールド!
グローバル: メッセージなし
ルーター: メッセージなし
上記のコード フラグメントは、モジュール/グローバルおよびクラス/クラス変数メカニズムが本質的に同一であることを示しています。
多くの変数を共有する場合、名前空間の汚染は、wall1、wall2 などのいくつかの壁タイプのモジュールを使用するか、単一のファイルでいくつかのルータータイプのクラスを定義することによって管理できます。後者は少し整頓されているため、おそらくクラス変数メカニズムを使用するための限界的な利点を表しています。
ディクショナリを使用して、モジュール間で変更可能な (または変更可能な) 変数を実現できます。
# 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 秒です。
これは、実際に欠けていると感じたいくつかの組み込みプリミティブ関数に使用します。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.
注:もちろん、これは filter と別の行を使用してゼロの長さをテストするか、一種の奇妙な行で reduce を使用して行うことができますが、私はいつもそれが奇妙だと感じていました.
__builtin__
これは、名前空間を変更するように聞こえます。それをするために:
import __builtin__
__builtin__.foo = 'some-value'
を直接使用しないでください__builtins__
(余分な "s" に注意してください)。明らかに、これは辞書またはモジュールである可能性があります。これを指摘してくれた ΤΖΩΤΖΙΟΥ に感謝します。詳細については、こちらを参照してください。
foo
どこでも使えるようになりました。
これを一般的に行うことはお勧めしませんが、これを使用するかどうかはプログラマ次第です。
割り当ては上記のように行う必要があります。設定foo = 'some-other-value'
するだけで、現在の名前空間にのみ設定されます。