19 ms·
If I understand the argument there correctly, the responder is saying: Nobody should ever use this functionality, instead they should always check that the date
by nbouscal 13y ago
If I understand the argument there correctly, the responder is saying: Nobody should ever use this functionality, instead they should always check that the date is not None. So, we should leave this broken, because we don't want to break backwards-compatibility with that class of applications that nobody should ever write.
That philosophy, taken to its logical conclusion, results in everything being broken forever.
- tomp 13y agoEquivalently, taken to its logical conclusion, it results in more people writing better code.
- tehwalrus 13y agoif var: ... is better code (for my value of better, which is subjective) than: if var is not None: ...
- batmansbelt 13y agoBy what criteria have you decided that?
- tehwalrus 13y agoquicker to scan-read ("code will be read many more times than it is written or modified", being the relevant axiom)
- Iftheshoefits 13y agoReading code is a purposeful activity, though; namely, to understand what the code does. The speed with which that can be done is relevant in the margins from a productivity standpoint, but to build an argument for code structure around it strikes me as missing the point of the "axiom" you quote.
- mildtrepidation 13y agoIn 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 >>>
- Cowen 13y agoI prefer the second one. Explicit is better than implicit.
- windsurfer 13y agoThe second what?
- Spiritus 13y agoThe second example: if var is not None: ...
- windsurfer 13y agoI was making a joke about being explicit versus implicit ;)
- pyre 13y agoIf explicit is always better than implicit, why is Python dynamically typed?
- lmm 13y agoBecause at the time it was originally written, it seemed impossible to write a statically typed language that was beautiful, or even readable. This has now proven to be false, and python is starting to add optional type annotations. It's not practical to introduce static typing more quickly - it would break too many existing programs.
- yxhuvud 13y agoSo why is it better to have to check for None but not having to check for midnight? The latter seems a lot less common and surprising.
- dagw 13y agoThey do two entirely different things in python. Occasionally you might actually want the functionality of the first statement, but if you write the first statement and expect it to do the same as the second statement, then that is a bug in your code. You could argue that the python is badly designed in this case and that the two should be equivalent, but that's a different argument.
- jofer 13y agoNot in python. if var: ... is better in some situations, but is objectively worse in many others. If you really do want anything that's "falsey" to fall into that conditional, then by all means, use it! Just be aware that `0`, `[]`, `None`, `0.0`, etc will all be treated the same. However, it's harmful in one of its most common use cases: default values. For example, let's say you're working with a function that takes an optional argument similar to: def foo(x, values=None): if values is None: values = [] You shouldn't use a mutable default argument for several reasons, so instead you make the default "None" and set it to an empty sequence. The snippet above is the standard idiom. Let's say a user mistakenly passes "values=0" instead of "values=[0]". If you had done: if not values: values = [] Then the code will happily proceed with "values" being an empty list and _silently give incorrect output_ instead of raising an error a couple of lines later. You can make the (very reasonable) argument that this is all the fault of dynamic typing, and if python was just a staticly typed language, the compiler would catch all of this, but that's beside the point. Be aware of what you're testing if you choose "if var:" instead of "if var is not None:"
- tehwalrus 13y agodefault values is a special case (and one which I consider to be a bug in python, frankly, since it bites everyone who didn't read up on default arguments before the wrote some code - everyone uses [] as a default argument at some point and then spends an amount of time proportional to the complexity of their program debugging the insane behaviour before noticing. My program was quite long and complex, and I am still bitter.) I didn't argue, and certainly didn't mean to imply, that it is always better, but in the sort of case we're considering in this example, i.e. we expect a valid time value or None, It really is madness to imply a time value of midnight is "empty".
- couchand 13y agoNice job explaining away one language bug with another.
- keypusher 13y agoOne of the core tenets of Python is that "explicit is better than implicit". So why is your way better than an explicit check?
- mcherm 13y agoThat is a rather silly statement since the two do not have the same behavior. So it is not a subjective question: one is right and the other is wrong. (For certain types, they do have the same behavior. In those cases, the subjective question is fine. But times are not a case where the behavior is the same.)
- jemfinch 13y ago"Also, beware of writing if x when you really mean if x is not None -- e.g. when testing whether a variable or argument that defaults to None was set to some other value. The other value might have a type (such as a container) that could be false in a boolean context!" From PEP-8: http://legacy.python.org/dev/peps/pep-0008/ http://legacy.python.org/dev/peps/pep-0008/
- nbouscal 13y agoWould you intentionally introduce language features that break functionality for people who don't follow style guidelines? I certainly hope not. The real problem with your argument is that the poorly-styled code of people who haven't learned better yet is in production. This isn't a theoretical exercise. This is a tool used in industry, and "teaching people to style their code better" is not a valid excuse for costing industrial users of the language money. Further, Python markets itself as a beginner-friendly language. Your attitude is the exact opposite of beginner-friendly.
- amirouche 13y agobeginner-friendly doesn't mean stupid-friendly. And I am in favor of "teaching people to style their code better" in the language even if in this case, it's not about style but the meaning of midnight. semantic != style. Also, language must also help/structure/offer rails for thinking, create et cetera. Industry must bend before truth, not bend truth over itself...
- nbouscal 13y agoWe have mostly the same principles but have come to different conclusions. The semantics of midnight are indeed what is important here, but midnight does not qualify as a zero. Zero implies identity for some addition, and there is no addition for which midnight is the identity. This is because midnight does not even support addition: you have to use timedeltas if you want to add times. Timedelta 0, then, is the proper zero, and should semantically be falsy in languages where zeros are falsy. Midnight, on the other hand, should not be. (The entire notion of falsiness is terrible and should crawl off somewhere and die, but that's beside the point.)
- amirouche 13y agoAgreed, midnight is not False.
- TheZenPsycho 13y ago>Would you intentionally introduce language features that break functionality for people who don't follow style guidelines? Uhm maybe I'm confused but isn't that the whole design philosophy behind python? It makes bad indentation a syntax error!
- josephlord 13y agoNo, it doesn't just different mistakes. If they wanted to make people write better code they would throw an error on coercion from time to bool so that everyone would have to fix the code.
- emillon 13y agoThis is what is plaguing the ocaml compiler and standard library. Overconservatism with respect to obscure features. For example, a patch was written to speed up hashtables (IIRC), and was rejected because it would change the result of hashing format strings (type-safe format strings have a different type from plain strings). I can't imagine a single application where you would need to preserve the value of hashed format strings. But specifying their value so that you can rely on them just seems to be a bad idea.
- rkangel 13y agoIt does sound like they might have gone a bit far, but as someone who works in an industrial context, a tool that maintains backwards compatibility rigorously is of enormous benefit. The case you might have to make to upgrade the version of the tool you are using has to take into account the risks, and something that is maintaining a high level of backwards compatibility has a much lower level of risk.
- sanderjd 13y agoHere are my preferences for tools, in order from most-preferred to least preferred: first, tools that have a rigorous deprecation process for breaking changes, distant second, tools that are incredibly conservative about breaking changes, pretty close third, tools that refuse to make breaking changes at all ever, astronomically distant last, tools that make breaking changes willy-nilly. I generally eventually have to re-write to use a totally different tool for either of the middle two cases, because they just can't keep up. I would much rather make changes to my use of them based on deprecations than be forced to ditch them entirely. (This is more a general statement - obviously refusing to make this datetime change isn't realistically going to push anybody away from Python.)
- throwaway7808 13y agoType-safe format strings should never be mixed with plain strings, constant strings, byte strings, unicode strings, batteries strings, byte array strings, char array strings, string buffers or any other type of string supported by ocaml. Keep your types pure and never mix them with any other types. Never. And you will never have any problem. And these python developers are lunatics. It is preposterous to use 'if' condition on a Date object and expect anything good. Idiots. They should have at least written a type-safe wrapper.
- rkangel 13y agoMy understanding is that the responder is saying that "That test does not mean what you are intending it to mean, it means something else that we've documented. We won't make it mean what you would like it to take make your incorrect code work, at the expense of breaking code that is using it in the documented way". I started on the side of the original person but was persuaded round by the responder. "if x:" means something completely different than "if x is not None", adn that needs to be understood. The fact that they might evaluate to the same result a lot of the time is luck, and is how people have got into this mess. Changing the boolean evaluation in this case is actually making the mess even worse.
- nbouscal 13y agoI understand the distinction between the two ways of writing the conditional. The point is that the documented way is surprising, and as far as I can tell everyone agrees that it is wrong. It's really not a matter of making the original poster's code work, it's a matter of making the language constructs have the expected behavior. Everyone seems to agree that code that used this behavior in the documented way would be bad code. That being the case, I see no way in which changing the behavior to the expected behavior would make anything worse.
- donaldstufft 13y agoYou can't document your way out of a usability problem.
- davidgerard 13y agoThere's a lot of maintainers who seem convinced otherwise.
- baq 13y agowhy is there anything in this thread besides your post is beyond me.
- thaumasiotes 13y agoThis is a nice way of putting things. There's a school of thought that says if things work how it says somewhere that they should work, then no part of the system is exhibiting a problem. But just in this thread we can see Python's insane treatment of default function parameters called a "bug in the language". I've long been mad about what I can only think of as a bug in the Java spec: bit shifts use the base-32 modulus of their actual operand. Sure, the specification says that that's what they're supposed to do, but when I ask the JVM to fill a 32-bit value with 40 zeroes from the right, I expect one of the only two sane results -- an exception or whatever value 32 zero bits represents. I'm pretty sure there is no circumstance where shifting in 8 zeroes could be correct or useful.
- patmcguire 13y agoThis is one of the pet theories I've seen for why Lisp didn't become more popular - Common Lisp was standardized too early and thus nothing could ever be fixed.
- iandanforth 13y agoYes. This is where Linus would step in and say "SHUT THE FUCK UP! We don't break user space, EVER!" Developers who enter into the mindset that the users of their code are using it "wrong" are a blight and will always be a blight. Too bad Python has a BDFL and not a Raging DFL.
- deleted 13y ago[deleted]
- yxhuvud 13y agoLinus does NOT break backwards compatibility. That is what this change implies. Which doesn't mean I disagree with changing the behaviour, but I doubt Linus would use that reason for that.
- marcosdumay 13y agoIt's undocummented, and very complex to use. That mail does not even have sufficient information to understand how to use this "feature". I hightly doubt anybody uses it outside of the datetime codebase. I never saw Linus complaining about changing undocummented and not used behaviour.
- sirclueless 13y agoIt is documented. That's the strongest argument against changing it: it's a documented piece of user-facing behavior. The python developers are changing it anyways because they're practical people who have decided it is more likely that people wrote bugs into their code, than that they wrote code that depended correctly on the falsiness of UTC midnight.
- einhverfr 13y agoThis is true, but if it is documented it is still sufficiently oddball to be useless. Consider: Midnight UTC, timezone EST: True Midnight UTC, timezone CET: False Midnight UTC, timezone CST: True Midnight UTC, timezone WIT: False Midnight UTC, timezone PST: True Now the problem here is that it may well be documented but it is in fact unsafe to rely on in any context. The behavior is thus irretrievably broken, documented or not. It isn't even expert-friendly. The behavior, documented or not, is irretrievably broken. After all timezones west of GMT will never have false times. If there is a use case for this behavior, I sure can't see it. Unless you like bugs appearing when you change timezones.
- army 13y agoI would agree with his approach, but unfortunately the Python community has encouraged, to some extent at least, the use of implicit "truthiness" to do things like check for None, rather than explicit checks.
- Pacabel 13y agoI'm not sure if I'd say that it's the Python community that has encouraged that practice. I think it's more likely just a bad habit that some people may have picked up when using PHP or JavaScript, and mistakenly continued using after moving to Python. PEP 8 (http://legacy.python.org/dev/peps/pep-0008/#programming-recommendations http://legacy.python.org/dev/peps/pep-0008/#programming-reco...) is quite clear about this: "Comparisons to singletons like None should always be done with is or is not, never the equality operators. Also, beware of writing if x when you really mean if x is not None -- e.g. when testing whether a variable or argument that defaults to None was set to some other value. The other value might have a type (such as a container) that could be false in a boolean context!" PEP 8 is more representative of the actual Python community's views than the mistakes of some programmers who are more accustomed to certain languages that are not Python.