打印出斐波那契系列

时间:2014-11-07 14:15:08

标签: python python-3.x closures fibonacci

我正在尝试编写一个简单的Python程序。它应该返回一个返回连续斐波那契数字的闭包:

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

我在运行时遇到此错误: UnboundLocalError: local variable 'n_1' referenced before assignment

编辑:在我的原始帖子中,我没有在n = 1的定义中包含fibGen,但它实际上是一个拼写错误。无论如何,我仍会得到同样的错误。

3 个答案:

答案 0 :(得分:5)

Python基于绑定行为在编译时确定变量的范围。如果您指定一个名称,或将其用作import目标(以及其他一些方法),那么您将在范围内绑定该名称。

您绑定n_1函数中的n_2fib();两人都被分配到。这使得fib()中的这两个名称​​ local ,而Python甚至不会查看周围的范围。

您需要覆盖此行为,并且可以使用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告诉编译器显式您不希望它查看绑定行为,而是将名称视为闭包。

接下来,您在n测试的第一个分支中使用if,但您尚未在else分支之外的任何位置定义它。你应该在那里返回1

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

最后但并非最不重要的是,您可以使用元组赋值交换两个变量,不需要中介:

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

答案 1 :(得分:1)

您无法修改封闭变量,n_1,n_2位于enclosing空间,而不是在函数空间中,这就是为什么您无法改变变量。

使用nonlocal关键字

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

答案 2 :(得分:0)

我一直在回顾这些众所周知的算法中的一些,并认为我会在 Python 中使用闭包来分享我的斐波那契版本:

#!/usr/bin/env python

def fibonacci():
    a = 0
    b = 1

    def internal_fibonacci():
        nonlocal a, b
        a, b = b, a+b
        return a
    return internal_fibonacci


def main():
    f = fibonacci()
    for i in range(0,10):
        print("f(" + str(i) + ") => " + str(f()))


if __name__ == '__main__':
    main()

比这里提供的其他解决方案更优雅。