78

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のスコープルールについて何が欠けていますか?

4

5 に答える 5

159

グローバル変数は特別です。関数内の変数に割り当てようとする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の名前付けとバインドのルールの詳細については、名前付けとバインドも参照してください。

于 2009-05-30T14:12:14.883 に答える
15

これを理解する秘訣は、=を使用して変数に割り当てるときに、ローカル変数としても宣言することです。したがって、グローバル変数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)
  setAのファイル「scopeTest.py」、7行目
    print "割り当て前、aは%d"%(a)
UnboundLocalError:割り当て前に参照されるローカル変数'a'

これは、PythonがsetA(value)関数にaと呼ばれるローカル変数があると判断したことを示しています。これは、関数で割り当てるときに変更するものです。(printA()のように)関数内でaに割り当てない場合、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行の追加は、setA(value)関数で変数aを使用すると、ローカル変数ではなくグローバル変数について話していることをPythonに通知します。

于 2009-05-30T14:17:00.927 に答える
3

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

グローバル

メソッドの外部で定義した場合でも、メソッドの内部で使用する前に関数の内部。

于 2010-01-16T10:03:30.887 に答える
2

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

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

于 2009-05-30T22:26:57.287 に答える