5 ms·
In my opinion, the "explicit is better than implicit" mantra of Python (which I find very sensible) should immediately imply preference for the second, even in
by mildtrepidation 13y ago
In my opinion, the "explicit is better than implicit" mantra of Python (which I find very sensible) should immediately imply preference for the second, even in cases where the first is almost certainly not going to cause problems.
Testing for "not None" also immediately tells other devs at least something about what's going on. Example: If var is an argument to a function and you see "if var," really understanding what's going on means looking at all invocations of that function to see what's being passed in.
Further, in that scenario, it's possible that different types are being passed for that argument. While "if var" could make this work where "if var is not None" would break functionality, in my opinion, it should break. Without getting into arguments about static typing, "truthiness" allows both sloppy code and the accidental introduction of bugs that might otherwise be caught during development due to faulty logic from vague conditional checks.
- maxerickson 13y agoIt's a rule of thumb, not a mantra. I suppose the hilarious way to argue it would be to say that there is an implicit "all other things being equal" in front of each of those.
- mildtrepidation 13y agoCall it what you want; I'm not arguing it to be pedantic, I think it's a very practical approach. But if you prefer: All other things being equal, I see no reason to write code that needlessly introduces potential bugs and maintainability issues by ignoring the rule of thumb that explicit trumps implicit.
- maxerickson 13y agoIt's an old argument. I don't have real strong feelings about it. I think there is enough code doing one or the other out there that the end result is to understand well the ramifications of both, so it ends up a matter of taste. The documentation is pretty clear about it: http://docs.python.org/release/3.3.4/library/stdtypes.html#truth-value-testing http://docs.python.org/release/3.3.4/library/stdtypes.html#t... Which leads to this: >>> a=object() >>> bool(a) True >>>
- pyre 13y agoSo since we need to be explicit, it should be: if var in (None, 0, "", [], {}, ...): pass something like that? In general, most of those false-y values make sense. Midnight being a false-y value does not make sense. This seems to be a case of "we represent midnight as zero internally, and zero is false-y, so midnight should be false-y." This logic does not make sense to me. If they represented noon as 0 instead, should that evaluate to false, just because?
- mildtrepidation 13y agoIf you need to use a test like that, you've already gone too far down the road of lazy "falsey" value usage, and whoever wrote it didn't bother with the idea of sensible defaults or consistent typing/initialization. I agree that midnight evaluating to false is ridiculous (I wasn't aware of this, thankfully I've never run into it). I'm not sure where you got the idea that I support this, but I don't.
- pyre 13y agoIt's functionality that someone went out of their way to create: def __bool__(self): if self.second or self.microsecond: return True offset = self.utcoffset() or timedelta(0) return timedelta(hours=self.hour, minutes=self.minute) != offset http://hg.python.org/cpython/file/302c8fdb17e3/Lib/datetime.py#l1252 http://hg.python.org/cpython/file/302c8fdb17e3/Lib/datetime.... Now that I look at the actual code, it makes less sense. It's not just midnight that evaluates to False. It's midnight UTC that evals to False. So if your timezone is PST, then 8AM evals to False. Since most datetime.time() objects are timezone 'dumb' by default, this distinction doesn't matter so much, but I can see this still biting some people hard, even if "Midnight is false-y" made sense. Edit: Also, to the "explicit is better than implicit" crowd, notice this line (in core libs): if self.second or self.microsecond: return True It's not: if self.second != 0 or self.microsecond != 0: return True What could be more 'Pythonic' than the Python core libraries? Edit: s/EST/PST/ ^^;;
- lstamour 13y ago
- schrodinger 13y agoIf you shouldn't use non-booleans in an if statement, then why is it allowed? If it's allowed, it should behave in the way that would surprise developers the least. http://en.wikipedia.org/wiki/Principle_of_least_astonishment http://en.wikipedia.org/wiki/Principle_of_least_astonishment
- rat87 13y agoOnce 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 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 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).