Python関数のグローバル変数?


272

このような混乱のため、そもそもグローバル変数の使用は避けなければならないことはわかっていますが、グローバル変数を使用する場合、次の方法はそれらを使用する有効な方法ですか?(別の関数で作成された変数のグローバルコピーを呼び出そうとしています。)

x = "somevalue"

def func_A ():
   global x
   # Do things to x
   return x

def func_B():
   x = func_A()
   # Do things
   return x

func_A()
func_B()

x第二の機能が使用するのグローバルなコピーの同じ値があることをxそのfunc_a用途や修正を?定義後に関数を呼び出す場合、順序は重要ですか?


1
関数に変数が割り当てられているからといって、Pythonがそのような割り当ての前に参照を扱うと想定しないようにも注意してください。最初の割り当てまで、xを使用した場合、それはグローバルなものでもローカルなものでもありません。悪名高いUnboundLocalError例外が顔に出ます:)
osirisgothra

回答:


412

グローバル変数に単にアクセスしたい場合は、その名前を使用するだけです。ただし、その値を変更するには、globalキーワードを使用する必要があります。

例えば

global someVar
someVar = 55

これにより、グローバル変数の値が55に変更されます。それ以外の場合は、55をローカル変数に割り当てます。

関数定義のリストの順序は重要ではありません(それらが何らかの方法で相互に参照していない場合)、それらが呼び出される順序は重要です。


2
私が与えたコードでは、func_Bが(1)xのグローバルコピーに対して(func_Aから取得したように)、(2)ローカル変数xに対して、func_Aの結果と同じ値を使用して、または(3)を実行しています。値のないローカル変数x、および(コンパイラの観点から)「何らかの値」またはfunc_Aのxとの関係なし
Akshat Shekhar、2012

xin func_Bは、呼び出し先の戻り値から値を取得するローカル変数func_Aです。つまり、それはあなたの(2)になると思います
Levon

わかりました、xがfunc_Aによって生成されたある種のランダムなシーケンスであったとしましょう(つまり、func_Aは実行されるたびに異なるxを生成しました)。呼ばれた?もしそうなら、どうすれば修正できますか?
Akshat Shekhar、2012

1
はい、func_A実行のたびにグローバル変数を変更し、それfunc_Bを使用に戻す場合、func_B毎回変更された値で動作します。あなたの「それを修正する方法」についてはわかりません。現在/元の質問に対する最も役立つ回答を受け入れ、フォローアップ質問のように見える別の質問を開くことを検討することもできます。
Levon

1
実際には、xが何であるかによって異なります。xが不変である場合、func_Bのxは同じ値を保持していてもローカルで宣言されているため、その中に残ります。これはタプル、intsに適用されます。たとえば、それがリストのインスタンスであり、そうする場合x.append("...")、ローカル変数がグローバル変数を参照するため、変更されるのはグローバル変数xです。
jadkik94

111

Pythonスコープ内で、そのスコープ内でまだ宣言されていない変数に代入すると、その変数がキーワードでグローバルスコープ変数を参照するように関数の前に宣言されていない限り、新しいローカル変数が作成されますglobal

疑似コードの変更されたバージョンを見て、何が起こるかを見てみましょう。

# Here, we're creating a variable 'x', in the __main__ scope.
x = 'None!'

def func_A():
  # The below declaration lets the function know that we
  #  mean the global 'x' when we refer to that variable, not
  #  any local one

  global x
  x = 'A'
  return x

def func_B():
  # Here, we are somewhat mislead.  We're actually involving two different
  #  variables named 'x'.  One is local to func_B, the other is global.

  # By calling func_A(), we do two things: we're reassigning the value
  #  of the GLOBAL x as part of func_A, and then taking that same value
  #  since it's returned by func_A, and assigning it to a LOCAL variable
  #  named 'x'.     
  x = func_A() # look at this as: x_local = func_A()

  # Here, we're assigning the value of 'B' to the LOCAL x.
  x = 'B' # look at this as: x_local = 'B'

  return x # look at this as: return x_local

実際、func_B名前を付けた変数ですべてを書き直すことができx_local、それは同じように機能します。

順序は、関数がグローバルxの値を変更する演算を実行する順序にのみ関係します。したがって、この例ではをfunc_B呼び出してfunc_Aいるため、順序は関係ありません。この例では、順序は重要です。

def a():
  global foo
  foo = 'A'

def b():
  global foo
  foo = 'B'

b()
a()
print foo
# prints 'A' because a() was the last function to modify 'foo'.

global唯一のグローバルオブジェクトを変更するために必要とされます。宣言しなくても、関数内からアクセスできますglobal。したがって、次のようになります。

x = 5

def access_only():
  return x
  # This returns whatever the global value of 'x' is

def modify():
  global x
  x = 'modified'
  return x
  # This function makes the global 'x' equal to 'modified', and then returns that value

def create_locally():
  x = 'local!'
  return x
  # This function creates a new local variable named 'x', and sets it as 'local',
  #  and returns that.  The global 'x' is untouched.

create_locallyaccess_only- の違いは、をaccess_only呼び出さなくてもグローバルxにアクセスすることglobalであり、どちらcreate_locallyも使用しない場合globalでも、値を割り当てているため、ローカルコピーが作成されます。

ここでの混乱が、グローバル変数を使用すべきではない理由です。


2
これが実際に混乱することはないと思います。Pythonのスコープルールを理解する必要があるだけです。
Casey Kuball

20

他の人が指摘したようglobalに、関数でグローバル変数を変更できるようにするには、その関数で変数を宣言する必要があります。アクセスしたいだけの場合は必要ありませんglobal

これについてもう少し詳しく説明すると、「変更」の意味は次のとおりです。別のオブジェクトを指すようにグローバル名を再バインドする場合globalは、関数内で名前を宣言する必要があります。

オブジェクトを変更(変更)する多くの操作は、別のオブジェクトを指すようにグローバル名を再バインドしないため、関数で名前を宣言しなくてもすべて有効ですglobal

d = {}
l = []
o = type("object", (object,), {})()

def valid():     # these are all valid without declaring any names global!
   d[0] = 1      # changes what's in d, but d still points to the same object
   d[0] += 1     # ditto
   d.clear()     # ditto! d is now empty but it`s still the same object!
   l.append(0)   # l is still the same list but has an additional member
   o.test = 1    # creating new attribute on o, but o is still the same object

8

パラメータのデフォルト値としてグローバルを使用して、私を見つけた1つのケースを次に示します。

globVar = None    # initialize value of global variable

def func(param = globVar):   # use globVar as default value for param
    print 'param =', param, 'globVar =', globVar  # display values

def test():
    global globVar
    globVar = 42  # change value of global
    func()

test()
=========
output: param = None, globVar = 42

paramの値が42であると期待していました。サプライズです。Python 2.7は、関数funcを最初に解析したときにglobVarの値を評価しました。globVarの値を変更しても、paramに割り当てられたデフォルト値には影響しませんでした。以下のように、評価を遅らせることは、私が必要とするように機能しました。

def func(param = eval('globVar')):       # this seems to work
    print 'param =', param, 'globVar =', globVar  # display values

または、安全を確保したい場合は、

def func(param = None)):
    if param == None:
        param = globVar
    print 'param =', param, 'globVar =', globVar  # display values

空のリストをデフォルト値として割り当てる問題を思い出しました。そして、例のように、通常の比較ではなく、is何かがあるかどうかを確認するために使用します。None==
berna1111

6

関数内のグローバル変数に直接アクセスできます。そのグローバル変数の値を変更する場合は、「global variable_name」を使用します。次の例を参照してください。

var = 1
def global_var_change():
      global var
      var = "value changed"
global_var_change() #call the function for changes
print var

一般的に言って、これは良いプログラミング方法ではありません。名前空間ロジックを壊すことにより、コードの理解とデバッグが困難になる可能性があります。


2

globalグローバル変数に割り当てられた値を変更する場合は、宣言を使用する必要があります。

グローバル変数から読み取る必要はありません。オブジェクトのメソッドを呼び出しても(そのオブジェクト内のデータが変更されても)、そのオブジェクトを保持する変数の値は変更されないことに注意してください(反射マジックはありません)。


2
この文言は残念です。Pythonでは、変数に割り当てられた値は参照であるため、技術的には正しいです(そして、私があなたがそう言っていたことは間違いありません)。ケース- xs.append(xs.pop(0))なしでも問題なく動作しglobal xsます。

@delnan私の答えは慎重に表現されていますが、明確にします。
Marcin
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.