web-dev-qa-db-ja.com

Python関数のグローバル変数

このような混乱のため、最初からグローバル変数を使用しないようにする必要があることはわかっていますが、それらを使用する場合は、以下の方法を使用するのが有効な方法でしょうか。 (私は別の関数で作成された変数のグローバルコピーを呼び出そうとしています。)

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()

2番目の関数が使用するxは、func_aが使用および変更するxのグローバルコピーと同じ値を持っていますか?定義後に関数を呼び出すとき、順序は重要ですか?

231
Akshat Shekhar

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

例えば。

global someVar
someVar = 55

これにより、グローバル変数の値が55に変更されます。それ以外の場合は、55をローカル変数に代入するだけです。

関数定義リストの順番は関係ありません(それらが何らかの方法で互いに参照しないと仮定して)、それらが呼ばれる順番は関係ありません。

353
Levon

Pythonスコープ内では、そのスコープ内でまだ宣言されていない変数への代入は、新しいローカル変数exceptを作成します。その変数は、グローバルスコープ変数をキーワード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_Bfunc_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_onlyglobalを呼び出さないにもかかわらずグローバルxにアクセスしています、そしてcreate_locallyglobalも使用していませんが、それはassigning valueなのでローカルコピーを作成します。

ここでの混乱は、なぜグローバル変数を使うべきではないのかということです。

96
jdotjdot

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

それについてもう少し詳しく説明すると、「変更」の意味は次のとおりです。re-bindを使用して別のオブジェクトを指すようにするには、名前を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
17
kindall

これは、グローバルをパラメータのデフォルト値として使用した場合の問題の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
4
SoloPilot

関数内でグローバル変数に直接アクセスできます。そのグローバル変数の値を変更したい場合は、 "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
Noisy_Botnet

グローバル変数に割り当てられた値を変更したいときは、global宣言を使わなければなりません。

グローバル変数から読み取るためにそれを必要としません。オブジェクト上のメソッドを呼び出しても(そのオブジェクト内のデータが変更されても)、そのオブジェクトを保持している変数の値は変更されません(リフレクティブマジックがない)。

1
Marcin