尽管该程序说了实话(除非您更改了源代码),但它确实根据用户的输入说出了斐波那契数。考虑到先前问题的所有(或大部分)反馈,我编写了此程序以查看我的进步情况。

def get_fibonacci_sequence(max):
    '''
    Returns the Fibonacci sequence from the
    first to the nth Fibonacci number.
    '''

    fib1 = 1
    fib2 = 1
    result = [fib1, fib2]
    for i in range(2, max):
        result.append(fib1 + fib2)
        fib1 = fib2
        fib2 = result[i]
    return result

def get_nth_fibonacci(n):
    '''Returns the nth Fibonacci number.'''

    return get_fibonacci_sequence(n)[n - 1]

def main():
    print("Would you like to have the sequence or the number?")
    print("Enter 's' for sequence, and anything else for the number.")
    seqOrNum = input("> ")
    if seqOrNum == 's':
        print("Up to which number would you like the sequence up to?")
        max = int(input("> "))
        print("The sequence up to the {}th Fibonacci number:".format(max))
        print(get_fibonacci_sequence(max))
    else:
        print("Which Fibonacci number would you like to get?")
        max = int(input("> "))
        print("The {}th Fibonacci number is:".format(max),
              get_nth_fibonacci(max))

if __name__ == "__main__":
    main()


示例输出:

Would you like to have the sequence or the number?
Enter 's' for sequence, and anything else for the number.
> s
Up to which number would you like the sequence up to?
> 10
The sequence up to the 10th Fibonacci number:
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]


关注点:


我的文档字符串使用得很好吗?
它是否遵循惯例?


#1 楼

生成器,而不是列表

与其返回斐波纳契数的列表,不如返回一个斐波纳契数的列表,这将是非常有用的。也就是说,yield他们。这样,您甚至都不需要max:

def get_fibonacci_numbers():
    '''
    Generator for all the fibonacci numbers
    '''
    fib1 = 1
    fib2 = 1
    yield fib1
    yield fib2
    while True:
        yield fib1 + fib2
        fib1 = fib2
        fib2 = fib1 + fib2


注意,为清晰起见,实际上一次完成双重分配会更好:

def get_fibonacci_numbers():
    '''
    Generator for all the fibonacci numbers
    '''
    fib1, fib2 = 0, 1
    while True:
        yield fib2
        fib1, fib2 = fib2, fib1 + fib2


如果需要第一个n数字,可以使用itertools.islice

为什么要生成器?

您可以轻松地将生成器转换为特定大小的列表,因此不会丢失任何功能。但是,使用轻量级生成器可以做的事太多了,而使用列表则无法做。考虑一些简单的问题-超过1000的第一个斐波那契数是什么?

>>> next(dropwhile(lambda x: x < 1000, get_fibonacci_numbers()))


欧拉问题2:找到400万以下的偶数斐波纳契数之和?

>>> sum(i for i in takewhile(lambda x: x < 4e6, get_fibonacci_numbers()) if i%2 == 0)


无法使用列表。至少,除非您不知道在哪里停车,否则不然。

如果只需要n,那就是:

def get_nth_fibonacci(n):
    return next(itertools.islice(
        get_fibonacci_numbers(),
        n, None))


#2 楼

绝对是docstring的很好用法,但最好将get_fibonnaci_sequence docstring设为一行。简短的语言和一些简短的捷径使这变得容易:

def get_fibonacci_sequence(max):
    '''Return Fibonacci sequence from 1st-nth Fibonacci number.'''


您确实在很大程度上遵循了约定。好的名字和格式,但是我有一些注释。您可以在一行中分配fib1 = fib2 = 1,这更短,但也更清晰。

将两个最新值与整数存储值一起存储在序列中也很奇怪。如果您想节省访问列表的时间,请坚持使用并更新fib1fib2,然后再将值添加到列表中。

for i in range(2, max):
    fib2 = fib1 + fib2
    fib1 = fib2
    result.append(fib2)
return result


您可以进行两种分配但是在一行中,由于Python具有智能的多重分配:

    fib1, fib2 = fib2, fib1 + fib2


在执行任何分配之前,对右侧进行了全面评估,因此这可以满足您的需求,因为结果如下:

    # fib1 = 1, fib2 = 2
    fib1, fib2 = fib2, fib1 + fib2
    fib1, fib2 = 2, 1 + 2
    fib1, fib2 = 2, 3


现在评估完成,可以分配两个值。

您可以使用以下格式更好地格式化序列: '\n'.join(get_fibonacci_sequence(max))将它们放在新行上,或者', '如果您希望每个值之间使用逗号。这些看起来比默认列表格式更好。

那样,您应该避免使用max,因为它是Python中的内置函数,您可以对其进行阴影处理。相反,您通常可以使用max_value。在这种情况下,numnumber甚至都可以工作,我认为max与您的实际意图有些偏差。