2017-06-18 18 views
2

なぜ次のコードは無効です:このコードが有効であるもののネストされた関数定義と範囲(UnboundLocalError)

def foo1(x=5): 
    def bar(): 
     if x == 5: 
      x = 6 
     print(x) 
    bar() 

def foo2(x=5): 
    def bar(): 
     if x == 5: 
      print('ok') 
     print(x) 
    bar() 

foo2()あなたが期待する正確に何をしますが、foo1()が得られますラインif x == 5:UnboundLocalError: local variable 'x' referenced before assignmentである。後でコードのxの値を変更すると、この条件が無効になるのはなぜですか?

+1

Pythonはまず、コード内の割り当て操作を探します。それが起こった瞬間から、それはローカル変数と見なされます。それは実際にはそれほどエレガントでない結果です。 –

答えて

2

Pythonは最初にの変数がローカルであり、どの変数が外側スコープからフェッチされているかを検出する必要があります。それが割り当て探しことを行うためには、のように:

def foo1(x=5): 
    def bar(): 
     if x == 5: 
      x = 6 # an assignment, so local variable 
     print(x) 
    bar()

ポイントは、割り当てがどこでも発生する可能性があること、です。たとえば、最後の行です。それにもかかわらず、現時点ではどこかに譲渡があります。xはローカルです。したがって、最初のコード部分では、xはローカル変数です。しかし、それが割り当てられる前にそれをフェッチするので、Pythonはエラーになります。

あなたは外側のスコープからxにアクセスするためにnonlocalキーワードを使用することができます。

:あなたはインスタンスのためのように、機能に変数を割り当てることができ、については

def foo1(x=5): 
    def bar(): 
     nonlocal x 
     if x == 5: 
      x = 6 
     print(x) 
    bar()

def foo1(x=5): 
    def bar(): 
     if bar.x == 5: 
      bar.x = 6 
     print(bar.x) 
    bar.x = x 
    bar()

ただし、2つはではありません。同等の。前者ではxを変更すると、foo1スコープのxも変更されます。後者の例では、bar.xだけを変更します。もちろん、これらが可変オブジェクトの場合は、同じオブジェクトを変更します。

関連する問題