问题
I am trying to write a simple Python program. It's supposed to return a a closure that returns successive fibonacci numbers:
def fibGen():
n_1 = 0
n_2 = 0
n = 1
def fib():
if n_1 ==0 and n_2 ==0:
n_1 = 1
return n
else:
n = n_1 + n_2
n_2 = n_1
n_1 = n
return n
return fib
f = fibGen()
for i in range(0,10):
print(f())
I get this error at run time:
UnboundLocalError: local variable 'n_1' referenced before assignment
EDIT: In my original post, I had not included n = 1
in the definition of fibGen
but it was actually a typo. I would still get the same error anyway.
回答1:
Python determines the scope of variables at compile time, based on binding behaviour. If you assign to a name, or use it as an import
target (and a few other ways) you are binding the name in a scope.
You are binding to n_1
and n_2
in the fib()
function; both are being assigned to. This makes those two names local in fib()
, and Python won't even look at the surrounding scope.
You'll need to override this behaviour, and you can do this by using the nonlocal statement:
def fibGen():
n_1 = 0
n_2 = 0
def fib():
nonlocal n_1, n_2
if n_1 ==0 and n_2 ==0:
n_1 = 1
return n
else:
n = n_1 + n_2
n_2 = n_1
n_1 = n
return n
return fib
nonlocal
tells the compiler explicitly that you don't want it to look at binding behaviour but instead treat the names as closures.
Next, you are using n
in the first branch of the if
test, but you haven't defined it anywhere outside of the else
branch. You should just return 1
there anyway:
def fibGen():
n_1 = 0
n_2 = 0
def fib():
nonlocal n_1, n_2
if n_1 ==0 and n_2 ==0:
n_1 = 1
return n_1
else:
n = n_1 + n_2
n_2 = n_1
n_1 = n
return n
return fib
Last but not least, you can swap two variables by using tuple assignment, no intermediaries needed:
def fibGen():
n_1 = 0
n_2 = 0
def fib():
nonlocal n_1, n_2
if n_1 ==0 and n_2 ==0:
n_1 = 1
else:
n_1, n_2 = n_1 + n_2, n_1
return n_1
return fib
回答2:
You can't modified enclosing variables, n_1, n_2 is in enclosing
space not in space of function that's why you can't cahnge the variables.
Use nonlocal
keyword
def fibGen():
n_1 = 0
n_2 = 0
def fib():
nonlocal n_1, n_2
if n_1 ==0 and n_2 ==0:
n_1 = 1
return n_1 # return `n_1` here not `n`
else:
n = n_1 + n_2
n_2 = n_1
n_1 = n
return n
return fib
f = fibGen()
for i in range(0,10):
print(f())
来源:https://stackoverflow.com/questions/26803203/printing-out-the-fibonacci-series