web-dev-qa-db-ja.com

関数内でグローバル変数を使用する

関数内でグローバル変数を作成または使用する方法を教えてください。

ある関数でグローバル変数を作成した場合、そのグローバル変数を別の関数でどのように使用できますか?アクセスを必要とする関数のローカル変数にグローバル変数を格納する必要がありますか?

2782
user46646

グローバル変数を代入する各関数で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

その理由は、グローバル変数はとても危険なので、globalキーワードを明示的に要求することによって、あなたが本当にそれをやっているのかどうかを確かめたいということです。

グローバル変数をモジュール間で共有したい場合は、他の答えを見てください。

3855
Paul Stephenson

あなたの状況を正しく理解していれば、Pythonがローカル(関数)およびグローバル(モジュール)名前空間をどのように処理するかの結果です。

このようなモジュールがあるとしましょう。

# sample.py
myGlobal = 5

def func1():
    myGlobal = 42

def func2():
    print myGlobal

func1()
func2()

これは42を印刷すると期待するかもしれませんが、代わりに5を印刷します。すでに述べたように、func1()に 'global'宣言を追加すると、func2()は42を印刷します。

def func1():
    global myGlobal
    myGlobal = 42

ここで何が起こっているのかというと、Pythonは、明示的に指示されていない限り、関数内の任意の場所で、割り当てられたである名前はその関数に対してローカルであると見なします。名前からのreadingのみで、その名前がローカルに存在しない場合、名前を含むスコープ(例えばモジュールのグローバルスコープ)で名前を検索しようとします。

したがって、名前myGlobalに42を割り当てると、Pythonは同じ名前のグローバル変数を隠すローカル変数を作成します。そのローカルはスコープ外になり、 ガベージコレクションされたfunc1()が戻ったとき。その間、func2()は(変更されていない)グローバル名以外を見ることはできません。この名前空間の決定は、実行時ではなくコンパイル時に行われることに注意してください。代入する前にfunc1()内のmyGlobalの値を読み取ると、Pythonは既にローカルである必要があると判断しているため、UnboundLocalErrorが返されます。可変だが、それはそれに関連付けられた値をまだ持っていない。しかし 'global'ステートメントを使用することで、ローカルに割り当てるのではなく、他の場所で名前を探す必要があることをPythonに伝えます。

(この振る舞いは、主にローカル名前空間の最適化によるものだと思います。この振る舞いがなければ、PythonのVMは、関数の中に新しい名前が割り当てられるたびに少なくとも3回の名前検索を実行する必要があります。名前がモジュール/組み込みレベルで既に存在していないことを確認してください)。これは非常に一般的な操作をかなり遅くします)。

717
Jeff Shannon

あなたは namespaces の概念を探りたいと思うかもしれません。 Pythonでは、 module global dataの自然な場所です。

各モジュールには独自のプライベートシンボルテーブルがあり、モジュール内で定義されているすべての関数によってグローバルシンボルテーブルとして使用されます。したがって、モジュールの作成者は、ユーザーのグローバル変数との偶然の衝突を心配することなく、モジュール内でグローバル変数を使用できます。一方、自分が何をしているのかを知っていれば、関数の参照に使用されているのと同じ表記法でモジュールのグローバル変数modname.itemnameに触れることができます。

モジュール内グローバルの特定の使用法は、ここで説明されています - モジュール間でグローバル変数を共有する方法 、そして内容を完全にするためにここで共有されています:

単一のプログラム内でモジュール間で情報を共有するための標準的な方法は、特別な設定モジュール(多くの場合、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
195
gimel

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がやり過ぎるような小さなスクリプトでは有用です。

54
J S

すでに存在している答えに加えて、これをより混乱させるものにします。

Pythonでは、関数内でのみ参照される変数は 暗黙的にグローバル です。関数の本体内の任意の場所に変数に新しい値が割り当てられている場合、それは local と見なされます。関数内で変数に新しい値が代入されている場合、その変数は暗黙的にローカルであり、明示的に「グローバル」として宣言する必要があります。

最初は少し驚くべきことですが、ちょっと考えてみるとわかります。一方では、代入された変数に対してグローバルを要求することは、意図しない副作用に対するバーを提供します。一方、すべてのグローバル参照にglobalが必要な場合は、常にglobalを使用します。組み込み関数またはインポートされたモジュールのコンポーネントへのすべての参照をグローバルとして宣言する必要があります。この混乱は、副作用を識別するための世界的な宣言の有用性を無効にするでしょう。

出典:Pythonにおけるローカル変数とグローバル変数の規則は何ですか?

42
Rauni Lillemets

ある関数でグローバル変数を作成した場合、その変数を別の関数でどのように使用できますか?

以下の関数を使ってグローバルを作成できます。

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の "global"は、本当にグローバルではないことに注意してください - それはモジュールレベルに対してグローバルなだけです。そのため、それがグローバルであるモジュールで書かれた関数にのみ利用可能です。関数はそれらが書かれているモジュールを覚えているので、それらが他のモジュールにエクスポートされるとき、それらはグローバル変数を見つけるためにそれらが作成されたモジュールをまだ見ます。

同じ名前のローカル変数

同じ名前のローカル変数を作成すると、グローバル変数が隠されます。

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!!!'

自分が何をしているのか正確にわかっていない限り、グローバル変数と同じ名前のローカル変数を使用しないでください。私はまだそのような理由に遭遇していません。

37
Aaron Hall

並列実行では、何が起こっているのか理解できないと、グローバル変数は予期しない結果を引き起こす可能性があります。これは、マルチプロセッシング内でグローバル変数を使用する例です。各プロセスがそれ自身の変数のコピーで動作することがはっきりわかります。

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]
31
Bohdan

結局のところ、答えは常に簡単です。

これは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 __== '__main__':
    main()

この単純なコードはそのように機能し、実行されます。助けになれば幸いです。

22
user2876408

あなたが言っているのはこのような方法を使うことです:

globvar = 5

def f():
    var = globvar
    print(var)

f()  # Prints 5

しかし、もっと良い方法は次のようにグローバル変数を使うことです。

globavar = 5
def f():
    global globvar
    print(globvar)
f()   #prints 5

どちらも同じ出力になります。

21
gxyd

使用したいすべての関数でグローバル変数を参照する必要があります。

次のように:

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]
"""
20
Mohamed El-Saka

実際にグローバル変数をローカル変数に保存するのではなく、元のグローバル参照が参照する同じオブジェクトへのローカル参照を作成するだけです。 Pythonのほとんどすべてがオブジェクトを参照する名前であり、通常の操作では何もコピーされないことに注意してください。

識別子が事前定義されたグローバルを参照するタイミングを明示的に指定する必要がなかった場合、おそらく識別子が新しいローカル変数であるときを明示的に指定する必要があります(たとえば、 'var'コマンドのようなもので) JavaScriptで見られます)。ローカル変数は、重大で重要なシステムではグローバル変数よりも一般的であるため、ほとんどの場合、Pythonのシステムの方が理にかなっています。

could存在する場合はグローバル変数を使用し、存在しない場合はローカル変数を作成して、推測しようとした言語があります。ただし、これは非常にエラーが発生しやすくなります。たとえば、別のモジュールをインポートすると、誤ってその名前のグローバル変数が導入され、プログラムの動作が変更される可能性があります。

18
Kylotan

これを試して:

def x1():
    global x
    x = 6

def x2():
    global x
    x = x+1
    print x

x = 5
x1()
x2()  # output --> 7
15
Sagar Mehta

Onとadd onに続いて、ファイルを使用して、すべてローカルに宣言されているすべてのグローバル変数を格納してから、「import as」:

Initval.pyファイル

Stocksin = 300
Prices = []

ファイルgetstocks.py

import  initval as  iv

Def   getmystocks (): 
     iv.Stocksin  = getstockcount ()


Def getmycharts ():
    For ic in range (0,iv.Stocksin):

.....

12
user5473311

同じ名前のローカル変数がある場合は、 globals()関数 を使用します。

globals()['your_global_var'] = 42
12
Martin Thoma

グローバル配列の明示的な要素への書き込みは、明らかにグローバル宣言を必要としません。

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
11
Mike Lampton

私は他の答えのどれにもそれを見たことがないのでこれを加えています、そしてそれは似たような何かに苦しんでいる誰かのために役に立つかもしれません。 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

そして

from pickle import dump
def dumpfile(name):
    with open(name+".dat", "wb") as outfile:
        dump(globals()[name], outfile)
    return True

グローバルネームスペースに変数をダンプしたりロードしたりするだけです。超便利、ない大騒ぎ、大騒ぎ。確かにそれはpython 3だけです。

5
Rafaël Dera

変更を反映させたいクラスの名前空間を参照します。

この例では、ランナーはファイルconfigから max を使用しています。ランナーが使用しているときに、テストで max の値を変更する必要があります。

main/config.py

max = 15000

main/runner.py

from main import config
def check_threads():
    return max < thread_count 

テスト/ 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()
5
llewellyn falco