関数でグローバル変数を作成または使用するにはどうすればよいですか?
ある関数でグローバル変数を作成した場合、そのグローバル変数を別の関数で使用するにはどうすればよいですか? アクセスが必要な関数のローカル変数にグローバル変数を格納する必要がありますか?
関数でグローバル変数を作成または使用するにはどうすればよいですか?
ある関数でグローバル変数を作成した場合、そのグローバル変数を別の関数で使用するにはどうすればよいですか? アクセスが必要な関数のローカル変数にグローバル変数を格納する必要がありますか?
global
値を代入する各関数内でグローバル変数を宣言することにより、他の関数内でグローバル変数を使用できます。
globvar = 0
def set_globvar_to_one():
global globvar # Needed to modify global copy of globvar
globvar = 1
def print_globvar():
print(globvar) # No need for global declaration to read value of globvar
set_globvar_to_one()
print_globvar() # Prints 1
ローカル変数を作成するのか、グローバル変数を変更するのかが不明であるため、Python はデフォルトでローカル変数を作成し、キーワードglobvar = 1
で他の動作を明示的に選択させます。global
モジュール間でグローバル変数を共有する場合は、他の回答を参照してください。
私があなたの状況を正しく理解している場合、あなたが見ているのは、Python がローカル (関数) とグローバル (モジュール) の名前空間を処理する方法の結果です。
次のようなモジュールがあるとします。
# sample.py
myGlobal = 5
def func1():
myGlobal = 42
def func2():
print myGlobal
func1()
func2()
これが 42 を出力することを期待するかもしれませんが、代わりに 5 を出力します。既に述べたように、' global
' 宣言をfunc1()
に追加すると、func2()
42 が出力されます。
def func1():
global myGlobal
myGlobal = 42
ここで何が起こっているかというと、Python は、関数内の任意の場所に割り当てられた名前は、明示的に別段の指示がない限り、その関数に対してローカルであると想定しています。名前から読み取るだけで、その名前がローカルに存在しない場合は、含まれているスコープ (モジュールのグローバル スコープなど) で名前を検索しようとします。
したがって、 name に 42 を割り当てるとmyGlobal
、Python は同じ名前のグローバル変数をシャドウするローカル変数を作成します。そのローカルは範囲外になり、戻るときにガベージコレクションされます。func1()
その間、func2()
(変更されていない) グローバル名以外は表示されません。この名前空間の決定は、実行時ではなくコンパイル時に行われることに注意してください。値を代入する前にmyGlobal
insideの値を読み取ると、 Python はローカル変数である必要があると既に判断しているため、が得られます。にはまだ値が関連付けられていません。しかし、' ' ステートメントを使用することで、名前をローカルに割り当てるのではなく、別の場所で名前を探すように Python に指示します。func1()
UnboundLocalError
global
(私は、この動作は主にローカル名前空間の最適化によって発生したと考えています。この動作がなければ、Python の VM は、関数内で新しい名前が割り当てられるたびに、少なくとも 3 つの名前検索を実行する必要があります (名前が割り当てられていないことを確認するため)。 t はモジュール/ビルトイン レベルで既に存在します)。これにより、非常に一般的な操作が大幅に遅くなります。)
名前空間の概念を調べてみるとよいでしょう。Python では、モジュールはグローバルデータの自然な場所です。
各モジュールには独自のプライベート シンボル テーブルがあり、モジュールで定義されたすべての関数によってグローバル シンボル テーブルとして使用されます。したがって、モジュールの作成者は、ユーザーのグローバル変数との偶発的な衝突を心配することなく、モジュールでグローバル変数を使用できます。一方、自分が何をしているのかわかっている場合は、モジュールのグローバル変数に、その関数を参照するために使用されるのと同じ表記法で触れることができます
modname.itemname
.
global-in-a-module の特定の使用法については、ここで説明します - How do I share global variables across modules? 、完全を期すために、内容をここで共有します。
単一のプログラム内のモジュール間で情報を共有する標準的な方法は、特別な構成モジュール ( configまたはcfgと呼ばれることが多い) を作成することです。アプリケーションのすべてのモジュールに構成モジュールをインポートするだけです。その後、モジュールはグローバル名として使用可能になります。各モジュールのインスタンスは 1 つしかないため、モジュール オブジェクトに加えられた変更はすべての場所に反映されます。例えば:
ファイル: config.py
x = 0 # Default value of the 'x' configuration setting
ファイル: mod.py
import config
config.x = 1
ファイル: main.py
import config
import mod
print config.x
Python は単純なヒューリスティックを使用して、ローカルとグローバルの間で変数をロードするスコープを決定します。変数名が代入の左側にあるが、グローバルと宣言されていない場合、それはローカルであると見なされます。割り当ての左側に表示されない場合は、グローバルであると見なされます。
>>> import dis
>>> def foo():
... global bar
... baz = 5
... print bar
... print baz
... print quux
...
>>> dis.disassemble(foo.func_code)
3 0 LOAD_CONST 1 (5)
3 STORE_FAST 0 (baz)
4 6 LOAD_GLOBAL 0 (bar)
9 PRINT_ITEM
10 PRINT_NEWLINE
5 11 LOAD_FAST 0 (baz)
14 PRINT_ITEM
15 PRINT_NEWLINE
6 16 LOAD_GLOBAL 1 (quux)
19 PRINT_ITEM
20 PRINT_NEWLINE
21 LOAD_CONST 0 (None)
24 RETURN_VALUE
>>>
の割り当ての左側に表示される baz がfoo()
唯一のLOAD_FAST
変数であることを確認してください。
関数内でグローバル変数を参照する場合は、globalキーワードを使用して、どの変数がグローバルであるかを宣言できます。すべての場合に使用する必要はありません (誰かが間違って主張しているように) - 式で参照されている名前が、この関数が定義されている関数のローカルスコープまたはスコープで見つからない場合、グローバル間で検索されます変数。
ただし、関数でグローバルとして宣言されていない新しい変数に代入すると、暗黙的にローカルとして宣言され、同じ名前の既存のグローバル変数が上書きされる可能性があります。
また、そうではないと主張する OOP 熱狂者とは対照的に、グローバル変数は便利です。特に、OOP がやり過ぎである小さなスクリプトの場合はそうです。
ある関数でグローバル変数を作成した場合、その変数を別の関数で使用するにはどうすればよいですか?
次の関数でグローバルを作成できます。
def create_global_variable():
global global_variable # must declare it to be a global first
# modifications are thus reflected on the module's global scope
global_variable = 'Foo'
関数を記述しても、実際にはそのコードは実行されません。したがって、create_global_variable
関数を呼び出します。
>>> create_global_variable()
それが指しているオブジェクトを変更することを期待しない限り、そのまま使用できます。
例えば、
def use_global_variable():
return global_variable + '!!!'
これで、グローバル変数を使用できます。
>>> use_global_variable()
'Foo!!!'
グローバル変数が別のオブジェクトを指すようにするには、global キーワードを再度使用する必要があります。
def change_global_variable():
global global_variable
global_variable = 'Bar'
この関数を書いた後、実際にそれを変更するコードはまだ実行されていないことに注意してください。
>>> use_global_variable()
'Foo!!!'
したがって、関数を呼び出した後:
>>> change_global_variable()
グローバル変数が変更されていることがわかります。名前は次global_variable
を指すようになりました'Bar'
:
>>> use_global_variable()
'Bar!!!'
Python の「グローバル」は、真にグローバルではないことに注意してください。これは、モジュール レベルに対してのみグローバルです。したがって、グローバルであるモジュールで記述された関数でのみ使用できます。関数は、それらが記述されたモジュールを記憶しているため、他のモジュールにエクスポートされた場合でも、それらが作成されたモジュールを参照してグローバル変数を見つけます。
同じ名前のローカル変数を作成すると、グローバル変数が上書きされます。
def use_local_with_same_name_as_global():
# bad name for a local variable, though.
global_variable = 'Baz'
return global_variable + '!!!'
>>> use_local_with_same_name_as_global()
'Baz!!!'
しかし、その誤った名前のローカル変数を使用しても、グローバル変数は変更されません。
>>> use_global_variable()
'Bar!!!'
何をしているのかを正確に理解し、そうする非常に正当な理由がない限り、ローカル変数をグローバルと同じ名前で使用することは避けるべきであることに注意してください。私はまだそのような理由に遭遇していません。
コメントのフォローは次のように尋ねます。
クラス内の関数内でグローバル変数を作成し、別のクラス内の別の関数内でその変数を使用したい場合はどうすればよいですか?
ここで、通常の関数で行うのと同じ動作がメソッドで得られることを示します。
class Foo:
def foo(self):
global global_variable
global_variable = 'Foo'
class Bar:
def bar(self):
return global_variable + '!!!'
Foo().foo()
そしていま:
>>> Bar().bar()
'Foo!!!'
ただし、グローバル変数を使用する代わりに、クラス属性を使用して、モジュールの名前空間が乱雑になるのを避けることをお勧めします。また、ここでは引数を使用しないことに注意してください。self
これらは、クラス メソッド (通常の引数からクラス属性を変更する場合に便利cls
) または静的メソッド (noself
またはcls
) である可能性があります。
並列実行では、何が起こっているのか理解していないと、グローバル変数によって予期しない結果が生じる可能性があります。マルチプロセッシング内でグローバル変数を使用する例を次に示します。各プロセスが変数の独自のコピーで動作することがはっきりとわかります。
import multiprocessing
import os
import random
import sys
import time
def worker(new_value):
old_value = get_value()
set_value(random.randint(1, 99))
print('pid=[{pid}] '
'old_value=[{old_value:2}] '
'new_value=[{new_value:2}] '
'get_value=[{get_value:2}]'.format(
pid=str(os.getpid()),
old_value=old_value,
new_value=new_value,
get_value=get_value()))
def get_value():
global global_variable
return global_variable
def set_value(new_value):
global global_variable
global_variable = new_value
global_variable = -1
print('before set_value(), get_value() = [%s]' % get_value())
set_value(new_value=-2)
print('after set_value(), get_value() = [%s]' % get_value())
processPool = multiprocessing.Pool(processes=5)
processPool.map(func=worker, iterable=range(15))
出力:
before set_value(), get_value() = [-1]
after set_value(), get_value() = [-2]
pid=[53970] old_value=[-2] new_value=[ 0] get_value=[23]
pid=[53971] old_value=[-2] new_value=[ 1] get_value=[42]
pid=[53970] old_value=[23] new_value=[ 4] get_value=[50]
pid=[53970] old_value=[50] new_value=[ 6] get_value=[14]
pid=[53971] old_value=[42] new_value=[ 5] get_value=[31]
pid=[53972] old_value=[-2] new_value=[ 2] get_value=[44]
pid=[53973] old_value=[-2] new_value=[ 3] get_value=[94]
pid=[53970] old_value=[14] new_value=[ 7] get_value=[21]
pid=[53971] old_value=[31] new_value=[ 8] get_value=[34]
pid=[53972] old_value=[44] new_value=[ 9] get_value=[59]
pid=[53973] old_value=[94] new_value=[10] get_value=[87]
pid=[53970] old_value=[21] new_value=[11] get_value=[21]
pid=[53971] old_value=[34] new_value=[12] get_value=[82]
pid=[53972] old_value=[59] new_value=[13] get_value=[ 4]
pid=[53973] old_value=[87] new_value=[14] get_value=[70]
結局のところ、答えは常に単純です。
以下は、main
定義で表示する簡単な方法を備えた小さなサンプル モジュールです。
def five(enterAnumber,sumation):
global helper
helper = enterAnumber + sumation
def isTheNumber():
return helper
main
定義でそれを示す方法は次のとおりです。
import TestPy
def main():
atest = TestPy
atest.five(5,8)
print(atest.isTheNumber())
if __name__ == '__main__':
main()
この単純なコードはそのように機能し、実行されます。お役に立てば幸いです。
あなたが言っているのは、次のような方法を使用することです:
globvar = 5
def f():
var = globvar
print(var)
f() # Prints 5
しかし、より良い方法は、次のようにグローバル変数を使用することです。
globvar = 5
def f():
global globvar
print(globvar)
f() #prints 5
どちらも同じ出力を提供します。
これを試して:
def x1():
global x
x += 1
print('x1: ', x)
def x2():
global x
x = x+1
print('x2: ', x)
x = 5
print('x: ', x)
x1()
x2()
# Output:
# x: 5
# x1: 6
# x2: 7
使用するすべての関数でグローバル変数を参照する必要があります。
次のように:
var = "test"
def printGlobalText():
global var #wWe are telling to explicitly use the global version
var = "global from printGlobalText fun."
print "var from printGlobalText: " + var
def printLocalText():
#We are NOT telling to explicitly use the global version, so we are creating a local variable
var = "local version from printLocalText fun"
print "var from printLocalText: " + var
printGlobalText()
printLocalText()
"""
Output Result:
var from printGlobalText: global from printGlobalText fun.
var from printLocalText: local version from printLocalText
[Finished in 0.1s]
"""
実際にはローカル変数にグローバルを保存するのではなく、元のグローバル参照が参照するのと同じオブジェクトへのローカル参照を作成するだけです。Python のほとんどすべてはオブジェクトを参照する名前であり、通常の操作では何もコピーされないことに注意してください。
識別子が事前定義されたグローバルをいつ参照するかを明示的に指定する必要がなかった場合、代わりに識別子が新しいローカル変数である場合を明示的に指定する必要があると思われます (たとえば、「var」コマンドのようなものを使用) JavaScript で見られます)。ローカル変数は、深刻で自明でないシステムではグローバル変数よりも一般的であるため、ほとんどの場合、Python のシステムの方が理にかなっています。
存在する場合はグローバル変数を使用し、存在しない場合はローカル変数を作成して、推測しようとする言語を持つことができます。ただし、これは非常にエラーが発生しやすくなります。たとえば、別のモジュールをインポートすると、その名前のグローバル変数が誤って導入され、プログラムの動作が変わる可能性があります。