patternpythonModerate
Telling fibonaccis to the user
Viewed 0 times
userthefibonaccistelling
Problem
Though this program tells the truth (unless you change the source code), it does tell Fibonacci numbers, depending on the user's input. Keeping in mind of all (or most) of the feedback given from previous questions, I wrote this program to see how well I have progressed.
Example Output:
Concerns:
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()Example Output:
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]Concerns:
- Are my docstrings well-used?
- Does it follow conventions?
Solution
Generators, not lists
Rather than returning a list of Fibonacci numbers, it would be much more useful to simply return an infinite generator of them. That is,
Note that double assigns are actually better done in one go for clarity:
If you want the first
Why a generator?
You can easily turn a generator into a list of specific size, so you're not losing any functionality this way. But there's simply so much you can do with a lightweight generator that you can't do with a list. Consider some simple problems - what's the first Fibonacci number over 1000?
Euler problem #2: find the sum of the even-valued fibonacci numbers under 4 million?
Can't do either with a list. At least, not unless you know where to stop up front.
If you want just the
Rather than returning a list of Fibonacci numbers, it would be much more useful to simply return an infinite generator of them. That is,
yield them. This way, you don't even need the 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 + fib2Note that double assigns are actually better done in one go for clarity:
def get_fibonacci_numbers():
'''
Generator for all the fibonacci numbers
'''
fib1, fib2 = 0, 1
while True:
yield fib2
fib1, fib2 = fib2, fib1 + fib2If you want the first
n numbers, you can use itertools.islice. Why a generator?
You can easily turn a generator into a list of specific size, so you're not losing any functionality this way. But there's simply so much you can do with a lightweight generator that you can't do with a list. Consider some simple problems - what's the first Fibonacci number over 1000?
>>> next(dropwhile(lambda x: x < 1000, get_fibonacci_numbers()))Euler problem #2: find the sum of the even-valued fibonacci numbers under 4 million?
>>> sum(i for i in takewhile(lambda x: x < 4e6, get_fibonacci_numbers()) if i%2 == 0)Can't do either with a list. At least, not unless you know where to stop up front.
If you want just the
nth one, that's:def get_nth_fibonacci(n):
return next(itertools.islice(
get_fibonacci_numbers(),
n, None))Code Snippets
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 + fib2def get_fibonacci_numbers():
'''
Generator for all the fibonacci numbers
'''
fib1, fib2 = 0, 1
while True:
yield fib2
fib1, fib2 = fib2, fib1 + fib2>>> next(dropwhile(lambda x: x < 1000, get_fibonacci_numbers()))>>> sum(i for i in takewhile(lambda x: x < 4e6, get_fibonacci_numbers()) if i%2 == 0)def get_nth_fibonacci(n):
return next(itertools.islice(
get_fibonacci_numbers(),
n, None))Context
StackExchange Code Review Q#114384, answer score: 16
Revisions (0)
No revisions yet.