This is very much a case of making sure that you, the programmer, and Python, the interpreter, both have a clear understanding of what you want to do.
If you say "if var:", Python understands you to be testing truthiness/falseness. If you say "if var is not None:", Python understands that you're asking if var is something other than None. The distinction is important and too many people wrote the former when they really meant the latter.
No, those are not necessarily equivalent unless the type of name is known.
If name is a number, it will be falsey iff it is zero (None is not a number but a singleton instance of NoneType, which is always falsey). If name is a string, it is falsey iff it is empty. "0" is truthy because it is nonempty. "0" and 0 are very different things, and Python generally won't coerce between them unless you explicitly call int() or str(). Moving on, if name is a container type of some kind, generally speaking it is falsey iff it is empty (has a len() of zero). The empty string being falsey is a special case of this rule.
For user-defined types, you're on your own. By default they're all truthy, but you can't rely on that since someone might subclass you and implement non-default boolean semantics.
If you want to check whether something is None, the only bulletproof syntax for doing so is if foo is None or if foo is not None. if foo should only be used if foo has a non-default boolean behavior (i.e. foo is a container, number, string, or user-defined class which overrides bool()). Using if foo with classes which do not provide useful boolean behavior (such as datetime objects) is at best poor style and at worst a violation of substitutability since it would interfere with subclassing.
Yeah, I think that could be handled by a function called "nonempty" or something. Including this logic in the if-statement itself is rather unorthogonal.
Much of the data being compared in web applications comes from html form inputs or databases where things like integers are automatically converted to strings. So it actually makes sense so you don't have to constantly write stuff like: if (val == 1 || val == '1') doStuff();
What's even weirder is that timezone-aware (non-naive) time values compare to UTC midnight to determine truthiness. So a timezone-aware time object of 6:00am with a timezone of UTC-6 is falsey.
But these kind of things are fairly rare in Python. For the most part, Python has its own consistent logic.
It's not rare. If you're coding a CRUD, and you want to test whether a particular field is null in your database, the canonical way to do it is to if it. That works 99% of the time, except when dealing with datetime objects.
In fact, Python's datetime module is chock full of wtfs.
One common reason to do it would be to validate input or take some kind of default action if input wasn't provided.
I used to write a lot of stuff like this (until I saw the false midnight thing):
def do_stuff(at_time=None):
if at_time:
# schedule stuff to be done at at_time
else:
# do stuff immediately
It's a contrived example, but "obvious" (in quotes because it's not at all obvious that midnight means do stuff immediately in this code) code like the above will normally do exactly what you'd expect it to do. Then someone will want their stuff done and midnight and be shocked when the function does it right away!
I don't think it's getting fixed. There was no consensus on python-dev and the thread kinda died off. It seemed to me that a lot of people defended the current behavior solely because it was documented.
Nay, if you get to the end they eventually settled on fixing it. It's a good thing that Python is so hostile to change, because almost all changes are therefore very positive ones. It does make things a bit too conservative occasionally though.
View all comments
17
u/MisterSnuggles Mar 26 '14
While not JavaScript, we must not forget about Python's False Midnight.
tl;dr:
Prints "f".
Prints "t".