各位好,以下是本人的code (是用很粗糙的backtracking寫法)
不知為何會出現 local variable "bitArr" referenced before assignment 這個錯誤
但若將bitArr = prevArr這行拿掉,就不會報錯了,蠻詭異的
敝人實在不知該從何debug起,煩請高手指點
class Solution(object):
def maxLength(self, arr):
"""
:type arr: List[str]
:rtype: int
"""
bitArr = [0]*26
self.res = 0
def backtracking(start):
self.res = max(self.res, sum(bitArr))
prevArr = bitArr
for i in range(start, len(arr)):
duplicate = False
for char in arr[i]:
if bitArr[ord(char)-ord('a')] == 1:
duplicate = True
bitArr = prevArr
break
bitArr[ord(char)-ord('a')] = 1
if duplicate:
continue
else:
for char in arr[i]:
bitArr[ord(char)-ord('a')] = 1
backtracking(i+1)
for char in arr[i]:
bitArr[ord(char)-ord('a')] = 0
backtracking(0)
return self.res
下方這段程式,會在 func 內產生一個 區域變數 a
在 Python 中對變數賦值,就相當於是在宣告區域變數 (如果函數中變數不存在)
a = 0
def func():
a = 1
print(a) #1
func()
print(a) #0
相當於 JS 中的這段程式,差異在 JS 有 var 而 Python 沒有,所以就一律當作宣告變數區域變數處理。
var a = 0
function func(){
var a = 1
}
那這個錯誤是什麼?local variable "bitArr" referenced before assignment
下方這段程式,根據上面的範例我們知道 a = 2
會產生一個新的區域變數,那在這之前執行 b = a
會發生什麼? 雖然 a = 2 還未執行,但在函數中 a 已經被視為區域變數了,所以執行 b = a
其實是將 未賦值的區域變數 a 設定給 b,類似 JS 「提升(Hoisting)」 的概念。
a = 0
def func():
b = a
a = 2
func()
# local variable 'a' referenced before assignment
那回到你的程式碼,因為這裡使用了未賦值的 bitArr
,所以出錯了
self.res = max(self.res, sum(bitArr))
可以在函數的開頭使用 nonlocal
指定 bitArr 為非區域變數,這樣就能像 JS 一樣當作外部變數使用了
def backtracking(start):
nonlocal bitArr
...
詳細內容可以 Google 搜尋 「Python Scope (作用域)」
謝謝您
簡而言之,以這段code為例
a = 0
def func():
b = a
a = 2
func()
如果在函數內再define一次a,a就會成為區域變數,而在函數中,a = 2這行之前出現的a,都會是未賦值的(a有define但未賦值,類似JavaScript的hoisting),因此b=a這行會出錯。
這不知算不算是Python的一個坑。JavaScript中為了避免hoisting帶來的麻煩,已經儘量使用let和const取代var了。
這真的蠻坑的,一般不會特別注意這點 ╰( ̄▽ ̄)╭
區域變數
非區域變數
可否再問個基本問題...
我想使用global來解題,但是發現:
class Solution(object):
def maxLength(self, arr):
"""
:type arr: List[str]
:rtype: int
"""
bitArr = [0]*26
self.res = 0
def backtracking(start):
global bitArr
print(bitArr)
backtracking(0)
return self.res
會出現 name 'bitArr' is not defined 的錯誤,請問是為什麼呢?用nonlocal就沒問題,不過舊版的Python沒有nonlocal可用
global
是「全域變數」,nonlocal
是「外部變數」,兩者差異如下:
a = 0 #<-全域
def func1():
a = 1 #<-外部
def func2():
global a # 這裡的 a 是全域變數
a = 0 #<-全域
def func1():
a = 1 #<-外部
def func2():
nonlocal a # 這裡的 a 是外部變數
bitArr 宣告在函數中不是全域變數,所以出現 is not defined
未定義的錯誤。
感謝,很清楚
看來global也不太好用