関数でのグローバル変数の使用

2009年01月08日に質問されました。  ·  閲覧回数 3.3M回  ·  ソース

user46646 picture
2009年01月08日

関数でグローバル変数を作成または使用するにはどうすればよいですか?

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

回答

Paul Stephenson picture
2009年01月08日
4399

値を割り当てる各関数内でグローバル変数を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キーワードを明示的に要求することで、それが実際に遊んでいることを確実に認識したいからだと思います。

モジュール間でグローバル変数を共有する場合は、他の回答を参照してください。

Jeff Shannon picture
2009年01月08日
790

私があなたの状況を正しく理解している場合、あなたが見ているのは、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は、関数内の任意の場所に割り当てられた名前は、特に明記されていない限り、その関数に対してローカルであると想定しているということです。 名前から読み取るだけで、名前がローカルに存在しない場合は、含まれているスコープ(モジュールのグローバルスコープなど)で名前を検索しようとします。

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

(この動作は主にローカル名前空間の最適化によって発生したと思います-この動作がないと、PythonのVMは、関数内で新しい名前が割り当てられるたびに、少なくとも3つの名前ルックアップを実行する必要があります(名前が確実にモジュール/ビルトインレベルですでに存在しているため、非常に一般的な操作が大幅に遅くなります。)

gimel picture
2009年01月08日
233

名前空間の概念を調べたいと思うかもしれません。 Pythonでは、モジュールグローバルデータの自然な場所です。

各モジュールには独自のプライベートシンボルテーブルがあり、モジュールで定義されているすべての関数によってグローバルシンボルテーブルとして使用されます。 したがって、モジュールの作成者は、ユーザーのグローバル変数との偶発的な衝突を心配することなく、モジュール内のグローバル変数を使用できます。 一方、自分が何をしているのかがわかっている場合は、モジュールの関数を参照するために使用されるのと同じ表記法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
SingleNegationElimination picture
2011年07月12日
97

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変数である方法を確認してください。

J S picture
2009年01月08日
64

関数内でグローバル変数を参照する場合は、 globalキーワードを使用して、どの変数がグローバルであるかを宣言できます。 すべての場合に使用する必要はありません(ここで誰かが誤って主張しているように)-式で参照されている名前がローカルスコープまたはこの関数が定義されている関数のスコープで見つからない場合は、グローバルで検索されます変数。

ただし、関数でグローバルとして宣言されていない新しい変数に割り当てると、暗黙的にローカルとして宣言され、同じ名前の既存のグローバル変数を覆い隠す可能性があります。

また、グローバル変数は、そうでないと主張する一部のOOP熱狂者とは対照的に、特にOOPがやり過ぎである小さなスクリプトの場合に役立ちます。

Aaron Hall picture
2016年01月02日
56

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

次の関数を使用してグローバルを作成できます。

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引数からクラス属性を変更する場合に便利)または静的メソッド( selfまたはcls )。

Rauni Lillemets picture
2014年07月04日
50

既存の回答に加えて、これをより混乱させるために:

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

最初は少し意外でしたが、少し考えてみるとこれがわかります。 一方では、割り当てられた変数にグローバルを要求することは、意図しない副作用に対する障害を提供します。 一方、すべてのグローバル参照にグローバルが必要な場合は、常にグローバルを使用することになります。 組み込み関数またはインポートされたモジュールのコンポーネントへのすべての参照をグローバルとして宣言する必要があります。 この混乱は、副作用を特定するためのグローバル宣言の有用性を損なうことになります。

出典: Pythonのローカル変数とグローバル変数のルールは何ですか?

Bohdan picture
2013年10月03日
36

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

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]
user2876408 picture
2013年10月14日
27

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

これは、 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()

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

gxyd picture
2014年12月04日
26

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

globvar = 5

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

f()  # Prints 5

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

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

どちらも同じ出力を提供します。