Pythonのモジュール間でグローバル変数を共有できることは知っています。ただし、これが可能な範囲と理由を知りたいのですが。例えば、
global_mod.py
x = None
mid_access_mod.py
from global_mod import *
class delta:
def __init__(self):
print x
bot_modif_mod.py
import mid_access_mod
import global_mod
class mew:
def __init__(self):
global_mod.x = 5
def main():
m = mew()
d = mid_access_mod.delta()
すべてのモジュールがグローバル変数xを共有している場合でも、Noneが出力されます。これはなぜですか? xはmew()によってbot_modif_mod.pyに割り当てられる前にmid_access_mod.pyで評価されるようです。
これは、不変の値(intおよびNone)を使用しているために発生します。変数のインポートは、参照渡しではなく、値渡しのようなものです。
Global_mod.xをリストにして、その最初の要素を操作すると、期待どおりに機能します。
from global_mod import x
を実行すると、x
がglobal_mod
で持っているのと同じ値を使用して、モジュールにx
という名前を作成します。関数やクラスなどの場合、これは期待どおりに機能します。これは、人々が(通常)後でそれらの名前に再割り当てしないためです。
Alexが指摘するように、import global_mod
を使用し、次にglobal_mod.x
を使用すると、問題を回避できます。モジュールで定義する名前はglobal_mod
で、常に必要なモジュールを参照します。次に、属性アクセスを使用してx
で取得すると、x
の最新の値が取得されます。
from whatever import *
はnotをコードで使用するのに適したイディオムです-これは、インタラクティブセッションで、タイピングを節約するショートカットとして使用することを目的としています。基本的に、その時点でのモジュールのすべての名前を「スナップショット」します。これらの名前のいずれかを再バインドすると、スナップショットが古くなり、あらゆる種類の問題が発生します。そして、それは、惨めなfrom ... import *
構文を使用してサインアップしている不可解な混乱の始まりにすぎません。
私のアドバイスが欲しいですか?その構造が既存のものであり、二度と使用しないことについて聞いたことはありません。 import global_mod as m
を使用し、その後は常に使用qualifiedm.x
などの名前--修飾名はso単なるベアネームよりもPythonではるかに便利で強力です、それも面白いことではありません。 (import
ステートメントのas m
部分は完全にオプションであり、基本的には簡潔にする目的で存在するか、名前の衝突に関するいくつかの問題を回避するために存在します。便利な場合に使用してください。不利な点はありませんが、必要でないと感じた場合でも、使用を強いられたり、強く勧められたりすることはありません)。
Ned Batchelderが述べたように、値だけが共有され、実際のオブジェクトは共有されません。参照によってオブジェクトを共有する場合は、おそらくThread-Local Data
。
例えば:
import threading
g = threading.local()
g.population = '7 Billion'
これで、変数g.populationにアクセスしたり、変数を変更したりすると、アクセスしようとしているスレッドと同じである場合、更新された値が取得されます。
Pythonドキュメント: https://docs.python.org/3/library/threading.html#thread-local-data で詳細を読む
この問題を解決するには、from global_mod import *
〜import global_mod
。
そして新しいmid_access_mod.pyは次のようになります:
import global_mod
class delta:
def __init__(self):
print global_mod.x
その理由は、 here にあります。
Pythonでの参照と名前のバインディングの動作方法により、モジュールの一部のシンボル(たとえば、foo.bar)をそのモジュールの外部から更新し、他のインポートコードで変更を確認するには、foo aをインポートする必要があります。特定の方法。
Xのリストを使用するように例を変更し、リストの割り当て(x [0] = ..)をトップの回答で提案されているとおりに印刷し、印刷が同じ初期値(None)を返しました。これにより、「from global_mod import * "は、変更可能かどうかに関係なく、コピーです。
コメントで示唆されているように、「print global_mod.x =がmid_access_modで使用される場合、「import global_mod」は機能します。