Once upon a time there was a language called Smalltalk that was the grandfather of dynamically typed languages. Perhaps partially as a consequence of implementing if else as methods on the boolean classes taking block closures to be executed only booleans were allowed(anything else is a missing method). If you wanted to test for null(Nil) you had to say something like
self foo isNil ifTrue: [self defaultFoo]
later some implementations added a method on object to test for nil
self foo ifNil: [self defaultFoo]
if you had to test for nil before testing for a condition it would be a bit ugly.
self foo ifNil: [((self foo) isFooish) ifTrue: [self defaultFoo]]
In ruby which was developed about a bit later perhaps to late to influence pythons bool handling they got rid of this problem by treating either nil or false as Falsey and everything else as truthy.
In python everything is true except:
None
False
zero of any numeric type, for example, 0, 0L, 0.0, 0j.
any empty sequence, for example, '', (), [].
any empty mapping, for example, {}.
instances of user-defined classes, if the class defines a __nonzero__() or __len__() method, when that method returns the integer zero or bool value False. [1]
http://docs.python.org/2/library/stdtypes.html
In python 3 __nonzero__ is __bool__
The reason for 0 being a truthy value arguably is arguably due to historical reasons. false used to be 0 and truth used to be 1, when they introduced a bool type they made it be an integer.
Some of the important python people(who are much better programmers then me) may disagree(
http://stackoverflow.com/a/3175293/259130) but I think
it was a ugly stain and should have been removed in python3 along with the whole 0(of any numeric type) being falsey.
The upside to python behaving like this is that in many situations you don't care what kind of falsey value you may have and you can write
if person and person.name:
instead of
if person != None and person.name != None and person.name != "":
and
if students and "John" in students and students[John"].age and students[John"].friends:
print "John has friends"
instead of
if students != None and "John" in students and students[John"].age != None and len(students[John"].friends) > 0:
print "John has friends"
There are downsides to this and people may have a strong personal preference for personal
scripts and you can argue that the ruby way or even the smalltalk way is conceptually nicer(and more "explicit")
but this is proper pythonic style and generally you should use it in python(maybe not the numerical one except when getting len of a collection)(unless you specifically depend on different code for different falsey values).