Skip to main content
 首页 » 编程设计

python之使用闭包实现 python 生成器

2025年05月04日9mengfanrong

我怎样才能去掉 fib_gen2 中的全局变量?我不想根据此 gist 使用 native 生成器或类,这是一个学术练习,尽管我对任何实现的改进感兴趣。

def ftake(fnext, last): 
    return [fnext() for _ in xrange(last)] 
 
def fib_gen2(): 
    global a; a = 1 
    global b; b = 1 
    def next(): 
        global a; global b; 
        r = a 
        a, b = b, a + b 
        return r 
    return next 
 
assert [1,1,2,3,5] == ftake(fib_gen2(), 5) 

请您参考如下方法:

在 Python 3.x 中,您可以使用 nonlocal statement :

def fib_gen2(): 
    a = b = 1 
    def next(): 
        nonlocal a, b 
        a, b = b, a + b 
        return b - a 
    return next 

在 Python 2.x 中,您需要使用一些技巧:

def fib_gen2(): 
    ab = [1, 1] 
    def next(): 
        ab[:] = ab[1], ab[0] + ab[1] 
        return ab[1] - ab[0] 
    return next 

这种不尽如人意的情况正是在 Python 3.x 中引入 nonlocal 的原因。

Python 没有变量声明,所以它必须自己弄清楚每个变量的作用域。它通过一个简单的规则来做到这一点:如果函数内部有一个名称赋值,则该名称是该函数的本地名称——除非明确声明为 global 或 nonlocal。在第二个示例中,名称 ab 没有赋值——列表已修改,但名称未重新赋值。因此范围是封闭函数。