私はこれを持っています:
g_c = 0
class TestClass():
global g_c
def run(self):
for i in range(10):
g_c = 1
print(g_c)
t = TestClass()
t.run()
print(g_c)
グローバル変数 g_c を実際に変更するにはどうすればよいですか?
global
アクセスする関数内で宣言することにより、次のようになります。
g_c = 0
class TestClass():
def run(self):
global g_c
for i in range(10):
g_c = 1
print(g_c)
Pythonのドキュメントには、global
ステートメントについて次のように記載されています。
グローバルステートメントは、現在のコードブロック全体を保持する宣言です。
global
関数内で宣言を移動する必要があります。
class TestClass():
def run(self):
global g_c
for i in range(10):
g_c = 1
print(g_c)
このステートメントは、Pythonコンパイラに、その名前への割り当て(およびその他のバインディングアクション)がグローバル名前空間の値を変更することを通知します。デフォルトでは、関数内の任意の場所に割り当てられている名前をローカル名前空間に配置します。このステートメントは、現在のスコープにのみ適用されます。
クラス本体g_c
に割り当てることはないので、ステートメントを入れても効果はありません。このステートメントは、それが使用されているスコープにのみ適用され、ネストされたスコープには適用されません。ステートメントのドキュメントを参照してください。これは次のように開きます。global
global
グローバルステートメントは、現在のコードブロック全体を保持する宣言です。
ネストされた関数とクラスは、現在のコードブロックの一部ではありません。
ここに、変化する状態を共有するためにグローバルを使用することに対する義務的な警告を挿入します。そうしないでください。そうしないと、コードの状態について推論するのが難しくなり、テストが難しくなり、リファクタリングが難しくなります。シングルトン状態(プログラム全体で1つの値)を変更し、少なくともクラス属性を使用します。
class TestClass():
g_c = 0
def run(self):
for i in range(10):
TestClass.g_c = 1
print(TestClass.g_c) # or print(self.g_c)
t = TestClass()
t.run()
print(TestClass.g_c)
名前空間に名前空間を付けて、外部から同じ値にアクセスする方法に注意してくださいTestClass
。
グローバル変数を使用することが最も便利な場合があることを理解しています。特に、クラスの使用が最も簡単なことを非常に困難にする場合(例:multiprocessing
)。グローバル変数の宣言で同じ問題に遭遇し、いくつかの実験でそれを理解しました。
クラス内g_c
の関数によって変更されなかった理由は、関数内でグローバル名への参照が正確に確立されていなかったためです。Python がグローバル宣言を処理する方法は、実際にはかなりトリッキーです。コマンドには次の 2 つの効果があります。run
g_c
global g_c
"g_c"
組み込み関数 によってアクセス可能なディクショナリへのキーの入り口を前提条件としますglobals()
。ただし、値が割り当てられるまでキーはディクショナリに表示されません。
g_c
(潜在的に) Python が現在のメソッド内で変数を探す方法を変更します。
(2) の完全な理解は特に複雑です。まず第一にg_c
、メソッド内で名前への割り当てが発生しない場合、Python はデフォルトでglobals()
. これは実際にはかなり一般的なことであり、コードの先頭でずっとインポートされているメソッド モジュール内で参照する場合と同様です。
ただし、代入コマンドがメソッド内のどこかg_c
で発生した場合、Python はデフォルトでローカル変数内で名前を検索します。これは、実際の割り当ての前に参照が発生した場合でも当てはまり、古典的なエラーにつながります。
UnboundLocalError: local variable 'g_c' referenced before assignment
現在、宣言がメソッド内のどこかglobal g_c
で発生した場合、参照または割り当ての後であっても、Python はデフォルトでグローバル変数内で名前を検索します。ただし、実験的な感じで参照の後に宣言を配置すると、警告が表示されます。g_c
SyntaxWarning: name 'g_c' is used prior to global declaration
考えてみれば、Python でグローバル宣言が動作する方法は、明らかに Python の通常の動作に織り込まれ、一貫しています。グローバル変数を実際に機能させたい場合にのみ、標準が煩わしくなります。
これは、私が今言ったことを要約したコードです (さらにいくつかの観察事項があります)。
g_c = 0
print ("Initial value of g_c: " + str(g_c))
print("Variable defined outside of method automatically global? "
+ str("g_c" in globals()))
class TestClass():
def direct_print(self):
print("Directly printing g_c without declaration or modification: "
+ str(g_c))
#Without any local reference to the name
#Python defaults to search for the variable in globals()
#This of course happens for all the module names you import
def mod_without_dec(self):
g_c = 1
#A local assignment without declaring reference to global variable
#makes Python default to access local name
print ("After mod_without_dec, local g_c=" + str(g_c))
print ("After mod_without_dec, global g_c=" + str(globals()["g_c"]))
def mod_with_late_dec(self):
g_c = 2
#Even with a late declaration, the global variable is accessed
#However, a syntax warning will be issued
global g_c
print ("After mod_with_late_dec, local g_c=" + str(g_c))
print ("After mod_with_late_dec, global g_c=" + str(globals()["g_c"]))
def mod_without_dec_error(self):
try:
print("This is g_c" + str(g_c))
except:
print("Error occured while accessing g_c")
#If you try to access g_c without declaring it global
#but within the method you also alter it at some point
#then Python will not search for the name in globals()
#!!!!!Even if the assignment command occurs later!!!!!
g_c = 3
def sound_practice(self):
global g_c
#With correct declaration within the method
#The local name g_c becomes an alias for globals()["g_c"]
g_c = 4
print("In sound_practice, the name g_c points to: " + str(g_c))
t = TestClass()
t.direct_print()
t.mod_without_dec()
t.mod_with_late_dec()
t.mod_without_dec_error()
t.sound_practice()
クラス内で変数をグローバルにするのは非常に簡単です。
a = 0
class b():
global a
a = 10
>>> a
10