python進階03UnboundLocalError和NameError錯誤

原創博客地址:python進階03UnboundLocalError和NameError錯誤

幾個概念

 

1
2
3
4
5
6
7
8
9
10
11
12
13
code block:作爲一個單元(Unit)被執行的一段python程序文本。例如一個模塊、函數體和類的定義等。
scope:在一個code block中定義name的可見性;
block’s environment:對於一個code block,其所有scope中可見的name的集合構成block的環境。
bind name:下面的操作均可視爲綁定操作
函數的形參
import聲明
類和函數的定義
賦值操作
for循環首標
異常捕獲中相關的賦值變量
local variable:如果name在一個block中被綁定,該變量便是該block的一個local variable。
global variable:如果name在一個module中被綁定,該變量便稱爲一個global variable。
free variable: 如果一個name在一個block中被引用,但沒有在該代碼塊中被定義,那麼便稱爲該變量爲一個free variable。

經典案例1

 

1
2
3
4
5
6
7
8
9
def outer_func():
    loc_var = "local variable"
    def inner_func():
        loc_var += " in inner func"
        return loc_var
    return inner_func

clo_func = outer_func()
clo_func()

錯誤提示:

 

1
2
3
4
5
6
Traceback (most recent call last):
  File "G:\Project Files\Python Test\Main.py", line 238, in <module>
    clo_func()
  File "G:\Project Files\Python Test\Main.py", line 233, in inner_func
    loc_var += " in inner func"
UnboundLocalError: local variable 'loc_var' referenced before assignment

經典案例2

 

1
2
3
4
5
6
def get_select_desc(name, flag, is_format = True):
    if flag:
        sel_res = 'Do select name = %s' % name
    return sel_res if is_format else name

get_select_desc('Error', False, True)

錯誤提示:

 

1
2
3
4
5
6
Traceback (most recent call last):
  File "G:\Project Files\Python Test\Main.py", line 247, in <module>
    get_select_desc('Error', False, True)
  File "G:\Project Files\Python Test\Main.py", line 245, in get_select_desc
    return sel_res if is_format else name
UnboundLocalError: local variable 'sel_res' referenced before assignment

經典案例3

 

1
2
3
4
5
6
7
8
9
10
11
def outer_func(out_flag):
    if out_flag:
        loc_var1 = 'local variable with flag'
    else:
        loc_var2 = 'local variable without flag'
    def inner_func(in_flag):
        return loc_var1 if in_flag else loc_var2
    return inner_func

clo_func = outer_func(True)
print clo_func(False)

錯誤提示:

 

1
2
3
4
5
6
Traceback (most recent call last):
  File "G:\Project Files\Python Test\Main.py", line 260, in <module>
    print clo_func(False)
  File "G:\Project Files\Python Test\Main.py", line 256, in inner_func
    return loc_var1 if in_flag else loc_var2
NameError: free variable 'loc_var2' referenced before assignment in enclosing scope

分析案例

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import sys
a = 1
for i in range(10):
    pass


def outer_func(g=3):
    loc_var = "local variable"

    def inner_func():
        print(a)
        print(g)

        try:
            int("0.2")
        except ValueError as e:
            print(e)

        loc_var += " in inner func"
        return loc_var

    return inner_func


clo_func = outer_func()
clo_func()


class clss():
    def add(self):
        pass

分析
1,雙下劃線:根據bind定義,識別爲scope可見的變量
2,scope可見是存在層次關係的,越靠左側說明包含範圍越大(類似作用域的感覺),越靠右側,包含範圍越小,(作用域越小)
3,圖中表明1和3的地方就是,標準案例1的問題點.loc_var由於在賦值語句“=”的左邊,所以別認爲是scope內(可見)變量,所以執行loc_var=loc_var+”xx”時,會從最近的scope加載loc_var,最近的loc_var恰好指向自己,但是此時的”loc_var”尚且未被初始化,所以報錯。
4,相比較,圖中2,變量”g”在局部也未被初始化,但是卻未報錯,應爲g在scope中未找到,所以自動向上找(往範圍更大的找),就找到入參處的變量”g”了。

參考

UnboundLocalError,探討Python中的綁定
Python UnboundLocalError和NameError錯誤根源解析

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章