闭包与函数属性?

时间:2016-02-05 03:53:50

标签: python-3.x

对于一个有趣的小项目,我创建了以下代码来练习函数中的非OOP状态保留。我想出了两种方法,然后意识到在第二个例子中嵌套inner_fib函数是多余的(似乎无论如何都运行正常)。我测试了所有这三个并得到了相同的结果。

从最佳实践的角度来看,一个优先于另一个? Func属性更简洁,但我可以看到它们让以后维护代码的人感到困惑。以下是我的例子:

def fib(first=0, second=1, temp=0):
    first = 0
    second = 1
    temp = 0
    def inner_fib():
        nonlocal temp, first, second
        temp = first + second
        first = second
        second = temp
        return first
    return inner_fib


def fib2():
    def inner_fib():
        inner_fib.temp = inner_fib.first + inner_fib.second
        inner_fib.first = inner_fib.second
        inner_fib.second = inner_fib.temp
        return inner_fib.first
    return inner_fib

def inner_fib():
    inner_fib.temp = inner_fib.first + inner_fib.second
    inner_fib.first = inner_fib.second
    inner_fib.second = inner_fib.temp
    return inner_fib.first

res = 0
a = inner_fib
a.first = 0
a.second = 1
a.temp = 0
while True:
    b = a()
    print(b, res + b)
    if b % 2 == 0 and b < 4000000:
        res += b
    elif res + b > 4000000:
        break
print(res)

1 个答案:

答案 0 :(得分:1)

老实说,两者都不是首选。正如您承认的那样,第二种方法相当于第三种方法(嵌套是多余的)。使用第三种方法,您有以下缺点:

  • inner_fib在您向其添加某些属性之前无效 - 潜在的错误来源
  • 你正在修补外部对象 - 糟糕的风格和潜在的错误来源

第一种方法略胜一筹,但变异闭合似乎有点矫枉过正。一种更易识别的方式(并且与标准库更兼容)将是使用生成器:

def fib(first=0, second=1, temp=0):
    first = 0
    second = 1
    temp = 0

    while True:
        temp = first + second
        first = second
        second = temp
        yield first

# in Python 3:
for _, x in zip(range(5), fib()):
    print(x)

可变类是另一种选择,具体取决于您将如何使用此功能。