2017-06-18 88 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()會給UnboundLocalError: local variable 'x' referenced before assignment在線if x == 5:。爲什麼在代碼中稍後改變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會對其進行錯誤處理。

可以使用nonlocal關鍵字從外部範圍訪問x

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

但請注意,兩者不是不是相當於。由於在前者中,如果您更改了x,它也會在foo1範圍內更改x。在後一個例子中,您只能修改bar.x。當然,如果這些是可變對象,你可以改變同一個對象。