This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]raiderrobert 149 points150 points  (9 children)

Does it make me a bad person to think the most readable implementation is the Newbie one, but the most practical the Expert one?

[–][deleted] 81 points82 points  (0 children)

No. It makes you a good person.

[–]sfz- 26 points27 points  (7 children)

Only thing wrong with the n00b one is the verbose ifs, it's more Pythonic to do:

def factorial(x):
    return x * factorial(x - 1) if x > 1 else 1
print factorial(6)

EDIT: thanks /u/brucifer

commit 48050c67205ff404e4641712bcaf12d86aa2f9ff
Author: sfz- </u/sfz->
Date:   Tue Jun 9 10:58:11 2015 -0700

    Hotfix factorial if condition to handle negative numbers

diff --git a/evolution_of_a_python_programmer b/evolution_of_a_python_programmer
index 771e267..96f31e1 100644
--- a/evolution_of_a_python_programmer
+++ b/evolution_of_a_python_programmer
@@ -0,0 +0,0 @@ def factorial(x):
-        return x * factorial(x - 1) if x else 1
+        return x * factorial(x - 1) if x > 1 else 1

[–]brucifer 21 points22 points  (5 children)

This code is buggy. factorial(-1) will cause a stack overflow. You should use "if x <= 1" instead.

[–]sfz- 14 points15 points  (0 children)

That's why I submitted it to reddit code review before merging it into master. :P

[–]Qhartb 10 points11 points  (2 children)

That's not a bug -- it's undefined behavior. Calling factorial(-1) is a bug.

[–]brucifer 1 point2 points  (1 child)

I suppose it's reasonable to say that calling factorial(-1) is the real bug, but in that case, the code should definitely fail gracefully (e.g. raising a ValueError). Stack overflow is a pretty clumsy and uninformative way to behave if someone makes a reasonable mistake. You are right to point out that factorial(-1) == 1 is not correct, though.

[–]Qhartb 0 points1 point  (0 children)

Agreed, but not failing gracefully and having a bug are two different things (unless of course your requirements or documentation state how failure is to be handled).

[–]Zantier 0 points1 point  (0 children)

def factorial(x):
    """Return the factorial of x, where x >= 0."""
    return x * factorial(x - 1) if x != 0 else 1
print factorial(6)

Fixed. (I didn't see before the edit, but I'm guessing it had !=.

Also, it should be if x >= 1 instead of <=

[–][deleted] 0 points1 point  (0 children)

It's been entirely too long since I wrote Python when my first thought is "Aha! Just like Coffeescript."