関数でグローバル変数を使用する
-
05-07-2019 - |
質問
関数でグローバル変数を作成または使用するにはどうすればよいですか
ある関数でグローバル変数を作成した場合、そのグローバル変数を別の関数で使用するにはどうすればよいですか?アクセスを必要とする関数のローカル変数にグローバル変数を保存する必要がありますか?
解決
グローバル変数は、それに割り当てる各関数で 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は 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
ここで行われていることは、関数内のどこにでも割り当てられるすべての名前は、特に明示的に指定されない限り、その関数に対してローカルであると仮定することです。名前から reading だけで、その名前がローカルに存在しない場合、含まれているスコープ(モジュールのグローバルスコープなど)で名前を検索しようとします。
名前 myGlobal
に42を割り当てると、Pythonは同じ名前のグローバル変数をシャドウするローカル変数を作成します。そのローカルは範囲外になり、のとき garbage-collected になりますfunc1()
は戻ります。一方、 func2()
は、(変更されていない)グローバル名以外は表示できません。この名前空間の決定は、実行時ではなくコンパイル時に行われることに注意してください-割り当てる前に func1()
内の myGlobal
の値を読み取ると、 dは UnboundLocalError
を取得します。これは、Pythonがローカル変数である必要があることを既に決定しているが、まだ関連付けられている値がないためです。しかし、 ' global
'ステートメントを使用することにより、Pythonに、ローカルに割り当てるのではなく、他の場所で名前を探すように指示します。
(この動作は主にローカル名前空間の最適化によって発生したと考えています-この動作がなければ、PythonのVMは関数内で新しい名前が割り当てられるたびに少なくとも3つの名前ルックアップを実行する必要があります(名前はモジュール/ビルトインレベルにまだ存在していませんでした)、これは非常に一般的な操作を大幅に遅くします)
名前空間の概念を調べてください。 Pythonでは、モジュールは global の自然な場所ですデータ:
各モジュールには独自のプライベートシンボルテーブルがあり、モジュールで定義されているすべての関数によってグローバルシンボルテーブルとして使用されます。したがって、モジュールの作成者は、ユーザーのグローバル変数との偶発的な衝突を心配することなく、モジュール内でグローバル変数を使用できます。一方、何をしているのかわかっている場合は、モジュールのグローバル変数を、その関数を参照するのに使用するのと同じ表記法
modname.itemname
で変更できます。
global-in-a-moduleの特定の使用については、ここで説明しています-グローバル変数をモジュール間で共有するにはどうすればよいですか。完全を期すために、ここで内容を共有します。
単一プログラム内のモジュール間で情報を共有する標準的な方法は、特別な構成モジュール( 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
>>>
foo()
の割り当ての左側に表示されるbazが、唯一の LOAD_FAST
変数である方法を参照してください。
関数でグローバル変数を参照する場合、 global キーワードを使用して、どの変数がグローバルであるかを宣言できます。すべての場合に使用する必要はありません(ここで誰かが誤って主張しているように)-式で参照される名前がローカルスコープまたはこの関数が定義されている関数のスコープで見つからない場合、グローバル間で検索されます変数。
ただし、関数でグローバルとして宣言されていない新しい変数に割り当てると、暗黙的にローカルとして宣言され、同じ名前の既存のグローバル変数を覆い隠すことができます。
また、特にそうではないと主張する一部のOOP熱狂者とは対照的に、グローバル変数は便利です-特に、OOPが過剰である小さなスクリプトの場合。
既存の回答に加えて、これをより混乱させるために:
Pythonでは、関数内でのみ参照される変数は 暗黙的にグローバル。変数に新しい値が割り当てられている場合 関数の本体内では、ローカルであると想定されます。変数の場合 関数内で新しい値が割り当てられると、変数は 暗黙的にローカルであり、それを明示的に‘ global’として宣言する必要があります。
最初は少し驚くべきことですが、ちょっとした考察で説明します この。一方では、割り当てられた変数にグローバルを要求すると、 意図しない副作用を防ぐ。一方、グローバルが すべてのグローバル参照に必要です。すべてのグローバル参照を使用します。 時間。組み込みへのすべての参照をグローバルとして宣言する必要があります 関数またはインポートされたモジュールのコンポーネント。この混乱は 特定するためのグローバル宣言の有用性を無効にする 副作用。
ある関数でグローバル変数を作成した場合、その変数を別の関数で使用するにはどうすればよいですか
次の関数を使用してグローバルを作成できます。
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!!!'
関数内からのグローバル変数の変更
グローバル変数を別のオブジェクトに向けるには、再度グローバルキーワードを使用する必要があります。
def change_global_variable():
global global_variable
global_variable = 'Bar'
この関数を書いた後、実際に変更するコードはまだ実行されていないことに注意してください:
>>> change_global_variable()
関数を呼び出した後:
>>> use_global_variable()
'Bar!!!'
グローバル変数が変更されたことがわかります。 global_variable
の名前は 'Bar'
を指すようになりました:
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!!!'
" global" Pythonでは真にグローバルではありません-モジュールレベルに対してのみグローバルです。そのため、グローバルなモジュールで記述された関数でのみ使用できます。関数は、作成されたモジュールを記憶しているため、他のモジュールにエクスポートされた場合、グローバル変数を見つけるために作成されたモジュールを引き続き調べます。
同じ名前のローカル変数
同じ名前でローカル変数を作成すると、グローバル変数が影になります:
<*>ただし、その誤った名前のローカル変数を使用しても、グローバル変数は変更されません。
<*>実行していることを正確に把握しており、実行する非常に正当な理由がない限り、グローバルと同じ名前のローカル変数の使用を避ける必要があることに注意してください。私はまだそのような理由に遭遇していません。
パラレル実行では、何が起こっているのか理解していない場合、グローバル変数が予期しない結果を引き起こす可能性があります。以下は、マルチプロセッシング内でグローバル変数を使用する例です。各プロセスが変数の独自のコピーで動作することを明確に見ることができます:
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
しかし、より良い方法は次のようなグローバル変数を使用することです:
globavar = 5
def f():
global globvar
print(globvar)
f() #prints 5
どちらも同じ出力を提供します。
使用するすべての関数でグローバル変数を参照する必要があります。
次のとおり:
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のほとんどすべてがオブジェクトを参照する名前であり、通常の操作では何もコピーされないことに注意してください。
識別子が事前定義されたグローバルを参照するタイミングを明示的に指定する必要がなかった場合、おそらく識別子が新しいローカル変数であるときを明示的に指定する必要があります(たとえば、 JavaScriptで見られるvar 'コマンド)。ローカル変数は、重大で重要なシステムではグローバル変数よりも一般的であるため、ほとんどの場合、Pythonのシステムの方が理にかなっています。
存在する場合はグローバル変数を使用し、存在しない場合はローカル変数を作成して、推測しようとする言語をできます。ただし、これは非常にエラーが発生しやすくなります。たとえば、別のモジュールをインポートすると、誤ってその名前のグローバル変数が導入され、プログラムの動作が変更される可能性があります。
これを試してください:
def x1():
global x
x = 6
def x2():
global x
x = x+1
print x
x = 5
x1()
x2() # output --> 7
同じ名前のローカル変数がある場合は、 globals()
関数。
globals()['your_global_var'] = 42
続いてアドオンとして、ファイルを使用して、すべてローカルに宣言されたすべてのグローバル変数を含め、 import as
:
ファイル initval.py :
Stocksin = 300
Prices = []
ファイル getstocks.py :
import initval as iv
def getmystocks():
iv.Stocksin = getstockcount()
def getmycharts():
for ic in range(iv.Stocksin):
グローバル配列の明示的な要素への書き込みには、グローバル宣言は必要ありませんが、「wholesale」への書き込みは必要です。その要件があります:
import numpy as np
hostValue = 3.14159
hostArray = np.array([2., 3.])
hostMatrix = np.array([[1.0, 0.0],[ 0.0, 1.0]])
def func1():
global hostValue # mandatory, else local.
hostValue = 2.0
def func2():
global hostValue # mandatory, else UnboundLocalError.
hostValue += 1.0
def func3():
global hostArray # mandatory, else local.
hostArray = np.array([14., 15.])
def func4(): # no need for globals
hostArray[0] = 123.4
def func5(): # no need for globals
hostArray[1] += 1.0
def func6(): # no need for globals
hostMatrix[1][1] = 12.
def func7(): # no need for globals
hostMatrix[0][0] += 0.33
func1()
print "After func1(), hostValue = ", hostValue
func2()
print "After func2(), hostValue = ", hostValue
func3()
print "After func3(), hostArray = ", hostArray
func4()
print "After func4(), hostArray = ", hostArray
func5()
print "After func5(), hostArray = ", hostArray
func6()
print "After func6(), hostMatrix = \n", hostMatrix
func7()
print "After func7(), hostMatrix = \n", hostMatrix
変更を表示するクラスの名前空間を参照します。
この例では、ランナーはファイル構成の max を使用しています。ランナーが使用しているときに、テストで max の値を変更する必要があります。
main / config.py
max = 15000
main / runner.py
from main import config
def check_threads():
return max < thread_count
tests / runner_test.py
from main import runner # <----- 1. add file
from main.runner import check_threads
class RunnerTest(unittest):
def test_threads(self):
runner.max = 0 # <----- 2. set global
check_threads()
これを追加しているのは、他の回答で見たことがないので、似たようなことに苦労している人にとっては役に立つかもしれません。 globals()
関数は可変グローバルを返します「魔法のように」できるシンボル辞書残りのコードでデータを利用できるようにします。
例:
from pickle import load
def loaditem(name):
with open(r"C:\pickle\file\location"+"\{}.dat".format(name), "rb") as openfile:
globals()[name] = load(openfile)
return True
and
from pickle import dump
def dumpfile(name):
with open(name+".dat", "wb") as outfile:
dump(globals()[name], outfile)
return True
変数をグローバル名前空間にダンプしたり、ロードしたりできます。非常に便利で、むちゃくちゃなく、大騒ぎしません。 Python 3のみであることを確認してください。