web-dev-qa-db-ja.com

Python 3:UnboundLocalError:代入前に参照されるローカル変数

次のコードはエラーUnboundLocalError: local variable 'Var1' referenced before assignmentを返します。

Var1 = 1
Var2 = 0
def function(): 
    if Var2 == 0 and Var1 > 0:
        print("Result One")
    Elif Var2 == 1 and Var1 > 0:
        print("Result Two")
    Elif Var1 < 1:
        print("Result Three")
    Var1 =- 1
function()

どうすればこれを修正できますか?助けてくれてありがとう!

145
Eden Crow

グローバルに頼るのではなく、パラメータを渡すことでこれを修正できます。

def function(Var1, Var2): 
    if Var2 == 0 and Var1 > 0:
        print("Result One")
    Elif Var2 == 1 and Var1 > 0:
        print("Result Two")
    Elif Var1 < 1:
        print("Result Three")
    return Var1 - 1
function(1, 1)
41
Jakob Bowyer

これは、Var1が存在していても、関数内でVar1という名前の代入ステートメントを使用しているためです(一番下の行にはVar1 -= 1)。当然のことながら、これはVar1と呼ばれる関数のスコープ内に変数を作成します(実際、-=または+=は既存の変数を更新(再割り当て)するだけですが、理由は不明(このコンテキストでは一貫性が高い)、Pythonは代入として扱います)。 Pythonインタプリタはこれをモジュールのロード時に見て、(正しいように)グローバルスコープのVar1をローカルスコープ内で使用すべきではないと決定します。これは、変数がローカルに割り当てられる前に参照しようとするときに問題になります。

グローバル変数を使うことは、必然的なことではありませんが、混乱して問題のあるコードにつながるため、通常Python開発者には嫌われます。しかし、コードが意味していることを達成するためにそれらを使用したい場合は、単に追加することができます。

global Var1, Var2

あなたの機能の上の中。これは、関数のローカルスコープ内でVar1またはVar2変数を定義するつもりはないことをPythonに伝えます。 Pythonインタプリタはこれをモジュールのロード時に見て、グローバルスコープ内で前述の変数への参照を検索するように(正しく)決定します。

いくつかのリソース

  • pythonのWebサイトには、この一般的な問題に関する すばらしい説明 があります。
  • Python 3は関連する nonlocal ステートメントを提供しています - それもチェックしてください。
331
orokusaki

関数内で変数の値を設定した場合、pythonはそれをその名前のローカル変数を作成するものとして解釈します。このローカル変数はグローバル変数をマスクします。

あなたの場合、Var1はローカル変数と見なされ、設定される前に使用されます。したがってエラーです。

この問題を解決するために、あなたの関数にglobal Var1を入れることでそれがグローバルだと明示的に言うことができます。

Var1 = 1
Var2 = 0
def function():
    global Var1
    if Var2 == 0 and Var1 > 0:
        print("Result One")
    Elif Var2 == 1 and Var1 > 0:
        print("Result Two")
    Elif Var1 < 1:
        print("Result Three")
    Var1 =- 1
function()
67
madjar

私はこの振る舞いが好きではありませんが、これがPythonのしくみです。この質問にはすでに他の人が答えていますが、完全を期すために、Python 2にはもっとそのような癖があることを指摘しておきましょう。

def f(x):
    return x

def main():
    print f(3)
    if (True):
        print [f for f in [1, 2, 3]]

main()

Python 2.7.6はエラーを返します。

Traceback (most recent call last):
  File "weird.py", line 9, in <module>
    main()
  File "weird.py", line 5, in main
    print f(3)
UnboundLocalError: local variable 'f' referenced before assignment

Pythonはf[f for f in [1, 2, 3]]ではローカル変数として使用されていることを見て、それがf(3)でもローカル変数であると判断します。 global fステートメントを追加することができます:

def f(x):
    return x

def main():
    global f
    print f(3)
    if (True):
        print [f for f in [1, 2, 3]]

main()

うまくいきます。しかし、fは最後に3になります...つまり、print [f for f in [1, 2, 3]]はグローバル変数f3に変更するので、もう関数ではありません。 。

幸いなことに、printに括弧を追加した後、Python 3ではうまくいきます。

9
osa

単純に計算値を返して、呼び出し側にグローバル変数を変更させないようにしてください。以下のように、関数内でグローバル変数を操作することはお勧めできません。

Var1 = 1
Var2 = 0

def function(): 
    if Var2 == 0 and Var1 > 0:
        print("Result One")
    Elif Var2 == 1 and Var1 > 0:
        print("Result Two")
    Elif Var1 < 1:
        print("Result Three")
    return Var1 - 1

Var1 = function()

または、グローバル変数のローカルコピーを作成してそれらを処理し、呼び出し元が適切に割り当てることができる結果を返すこともできます。

def function():
v1, v2 = Var1, Var2
# calculate using the local variables v1 & v2
return v1 - 1

Var1 = function()
2
ctx