web-dev-qa-db-ja.com

グローバル変数への割り当てがPythonで機能しないのはなぜですか?

pythonスコープルールを理解しようとすると、ひどい問題が発生します。

次のスクリプトを使用します。

a = 7

def printA():
    print "Value of a is %d" % (a)

def setA(value):
    a = value
    print "Inside setA, a is now %d" %(a)


print "Before setA"
printA()
setA(42)
print "After setA"
printA()

次の予期しない(私にとっての)出力を提供します。

 setA 
の前aの値は7 
 setA内では、aは42 
 setA 
の後aの値は7 [.____。です。 ]

Aの値の最後の出力が7ではなく42になると予想される場合、グローバル変数のスコープに関するPythonのスコープルールについて何が欠けていますか?

62
Free Wildebeest

グローバル変数は特別です。変数に割り当てようとするとa = value関数内では、同じ名前のグローバル変数が存在する場合でも、関数内に新しいローカル変数を作成します。代わりにグローバル変数にアクセスするには、関数内に globalステートメント を追加します。

a = 7
def setA(value):
    global a   # declare a to be a global
    a = value  # this sets the global value of a

Pythonの命名規則とバインディング規則の詳細な説明については、 命名とバインディング も参照してください。

116
Adam Rosenfield

これを理解する秘trickは、=を使用して変数に代入するときに、それをローカル変数としても宣言することです。したがって、グローバル変数aの値を変更する代わりに、setA(value)は実際にローカル変数(たまたまaと呼ばれる)を渡された値に設定します。

これは、次のようにsetA(value)の先頭でaの値を出力しようとすると、より明白になります。

def setA(value):
    print "Before assignment, a is %d" % (a)
    a = value
    print "Inside setA, a is now %d" % (a)

このPythonを実行しようとすると、役立つエラーが表示されます。

トレースバック(最後の最後の呼び出し):
ファイル「scopeTest.py」、14行目、
 setA(42)
ファイル「scopeTest.py」、 7行目、setA 
で「割り当て前、aは%d」を出力%(a)
 UnboundLocalError:割り当て前に参照されたローカル変数 'a' 

これは、PythonがsetA(value)関数にaというローカル変数があることを決定したことを示しています。これは、関数で割り当てたときに変更するものです。関数内のa(printA()と同様)の場合、Pythonはグローバル変数Aを使用します。

変数をグローバルとしてマークするには、Pythonでglobalキーワードグローバル変数を使用するスコープ内を使用する必要があります。この場合、setA(value)関数内にあります。したがって、スクリプトは次のようになります。

a = 7

def printA():
    print "Value of a is %d" % (a)

def setA(value):
    global a
    a = value
    print "Inside setA, a is now %d" %(a)


print "Before setA"
printA()
setA(42)
print "After setA"
printA()

この1行の追加により、Python setA(value)関数で変数aを使用すると、ローカル変数ではなくグローバル変数について話していることがわかります。

13
Free Wildebeest

Pythonには、他の言語のような変数の概念がありません。 「どこかに」あるオブジェクトがあり、これらのオブジェクトへの参照があります。 =は、これらのオブジェクトをcurrent名前空間の参照に割り当てるために使用されます。

値が参照するオブジェクトを参照するsetA関数の名前空間に名前aを作成します。

1
DasIch

関数内で、aはローカル変数として扱われます。定義する必要があります

グローバルな

関数内

1
appusajeev

関数を実行すると、関数のローカル変数に使用される新しいシンボルテーブルが導入されます。より正確には、関数内のすべての変数の割り当ては、ローカルシンボルテーブルに値を格納します。一方、変数参照は、最初にローカルシンボルテーブル、次に囲んでいる関数のローカルシンボルテーブル、次にグローバルシンボルテーブル、最後に組み込み名のテーブルを調べます。したがって、グローバル変数は、参照される場合もありますが、関数内で値を直接割り当てることはできません(グローバルステートメントで名前が付けられている場合を除く)。

0
Nilesh Jain