问题
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